package com.youlu.campus.service.order.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.google.common.collect.Lists;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.order.vo.OrderRequest;
import com.youlu.campus.common.utils.ExcelUtil;

import com.youlu.campus.common.utils.TimeUtils;
import com.youlu.campus.component.QiniuUtil;
import com.youlu.campus.component.SmsUtil;
import com.youlu.campus.entity.ActivityInfo;
import com.youlu.campus.entity.ActivityStatistics;
import com.youlu.campus.entity.CaGroupInfo;
import com.youlu.campus.entity.CaInfo;
import com.youlu.campus.entity.CaMaterialConfig;
import com.youlu.campus.entity.FileExportTask;
import com.youlu.campus.entity.ItemInfo;
import com.youlu.campus.entity.OOrderInfo;
import com.youlu.campus.entity.OrderCommentInfo;
import com.youlu.campus.entity.OrderInfo;
import com.youlu.campus.entity.OrderInfoTip;
import com.youlu.campus.entity.PayConfigPage;
import com.youlu.campus.entity.QQConfigInfo;
import com.youlu.campus.entity.RefundRecord;
import com.youlu.campus.entity.SmsTemplate;
import com.youlu.campus.entity.SubOrderInfo;
import com.youlu.campus.entity.SystemOptLog;
import com.youlu.campus.entity.UniversityInfo;
import com.youlu.campus.entity.UserCaRecord;
import com.youlu.campus.entity.UserInviteRecord;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.UserParticipateActivityInfo;
import com.youlu.campus.entity.VO.req.CreateCaOrderTagVO;
import com.youlu.campus.entity.VO.req.DeliveryOrderSubMsgMQVO;
import com.youlu.campus.entity.VO.req.DingTalkRobotRequest;
import com.youlu.campus.entity.VO.req.OrderRefundOptVO;
import com.youlu.campus.entity.VO.req.QQWxRefundRequest;
import com.youlu.campus.entity.VO.res.MyOrderResponse;
import com.youlu.campus.entity.VO.res.PaperCaOrderResponse;
import com.youlu.campus.entity.WechatConfigInfo;
import com.youlu.campus.entity.WechatH5UserPO;
import com.youlu.campus.entity.WechatMerchantConfig;
import com.youlu.campus.entity.ca.GiftCaInfo;
import com.youlu.campus.entity.course.dto.GoodsOrderDTO;
import com.youlu.campus.entity.data.OrderBatchRefundImport;
import com.youlu.campus.entity.domain.OrderImport;
import com.youlu.campus.entity.domain.OrderUpdateRequest;
import com.youlu.campus.entity.domain.ReDoOrderImport;
import com.youlu.campus.entity.domain.RefundOrderResult;
import com.youlu.campus.entity.kuaidi100.KuaiDi100PollMapBodyDTO;
import com.youlu.campus.entity.order.SharingProfitOrderDetail;
import com.youlu.campus.entity.order.SingleOrderBatch;
import com.youlu.campus.entity.order.dto.LogisticsOrderDto;
import com.youlu.campus.entity.system.UserDataPermission;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.activity.ActivityStatisticsService;
import com.youlu.campus.service.activity.impl.PlatformOtherActivityService;
import com.youlu.campus.service.base.BaseService;
import com.youlu.campus.service.ca.CaGroupInfoService;
import com.youlu.campus.service.ca.CaInfoService;
import com.youlu.campus.service.ca.CaMaterialConfigService;
import com.youlu.campus.service.ca.impl.CaCollectService;
import com.youlu.campus.service.ca.impl.UserCaRecordService;
import com.youlu.campus.service.cache.CacheCaInfoService;
import com.youlu.campus.service.cache.CachePayConfigService;
import com.youlu.campus.service.card.TsCardService;
import com.youlu.campus.service.config.WxPayConfig;
import com.youlu.campus.service.course.WechatPayService;
import com.youlu.campus.service.data.OrderStatisticsService;
import com.youlu.campus.service.dingtalk.DingTalkService;
import com.youlu.campus.service.file.FileExportTaskService;
import com.youlu.campus.service.file.FileService;
import com.youlu.campus.service.item.ItemInfoService;
import com.youlu.campus.service.notify.KuaiDi100Service;
import com.youlu.campus.service.order.DeliveryOrderSubMsgService;
import com.youlu.campus.service.order.LogisticsOrderService;
import com.youlu.campus.service.order.MerchantSharingProfitService;
import com.youlu.campus.service.order.OrderInfoTipService;
import com.youlu.campus.service.order.OrderService;
import com.youlu.campus.service.pay.UserPurchaseCaService;
import com.youlu.campus.service.platform.PlatformConfigService;
import com.youlu.campus.service.qq.QQConfigInfoService;
import com.youlu.campus.service.sms.SmsTemplateService;
import com.youlu.campus.service.system.SystemOptLogService;
import com.youlu.campus.service.system.UserDataPermissionService;
import com.youlu.campus.service.utils.CommonUtils;
import com.youlu.campus.service.utils.PayUtil;
import com.youlu.campus.service.wechat.WechatConfigInfoService;
import com.youlu.campus.service.wechat.WechatMerchantConfigService;
import com.youlu.campus.wechat.facotrys.WechatPayRefundServiceFacotry;
import com.youlu.campus.wechat.service.WeChatPayRefundService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 订单管理接口实现类
 *
 * @author: YangJ
 * @date: 2020/12/28 13:57
 */
@Slf4j
@Service("orderService")
public class OrderServiceImpl extends BaseService implements OrderService {
    @Autowired
    private CaInfoService caInfoService;
    @Autowired
    private WxPayConfig wxPayConfig;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private SmsUtil smsUtil;
    @Lazy
    @Autowired
    private ActivityService activityService;
    @Autowired
    private SmsTemplateService smsTemplateService;
    final private static String refundOrderNoPreKey = "luyou.campus.refund-order-no";
    @Autowired
    private FileService fileService;

    @Autowired
    private QiniuUtil qiniuUtil;
    @Autowired
    private FileExportTaskService fileExportTaskService;
    @Autowired
    private WechatConfigInfoService wechatConfigInfoService;
    @Autowired
    private OrderInfoTipService orderInfoTipService;
    @Autowired
    private WechatMerchantConfigService wechatMerchantConfigService;
    @Autowired
    private OrderStatisticsService orderStatisticsService;
    @Autowired
    private SystemOptLogService systemOptLogService;
    @Autowired
    private CaMaterialConfigService caMaterialConfigService;

    @Autowired
    private DeliveryOrderSubMsgService deliveryOrderSubMsgService;

    @Autowired
    private DingTalkService dingTalkService;

    @Autowired
    private TsCardService tsCardService;

    private static Long orderNoExpireTime = 365 * 24 * 3600 * 1000L;
    // 前端页面域名
//    @Value("${sys.pay.wx.bizFrontDomain:https://wechat-h5-test.gqgood.com}")
    /// /    private String bizFrontDomain;

    private String refundDesc = "纸质版名额有限，申请退款后将失去再次申请该活动纸质证书的资格，如需退款，请点击下方链接提交，提交后，将在3个工作日内完成退款，请放心等待：";

    private String refundUrl = "/h5/index.html?#/pages/order-refund-info?activityId=%s&id=%s&appId=%s";

    @Autowired
    private UserCaRecordService userCaRecordService;
    @Autowired
    private PlatformConfigService platformConfigService;
    @Autowired
    private ActivityStatisticsService activityStatisticsService;

    @Autowired
    private CaGroupInfoService caGroupInfoService;
    @Autowired
    private QQConfigInfoService qqConfigInfoService;
    @Autowired
    private ItemInfoService itemInfoService;
    @Autowired
    private WechatPayService wechatPayService;

    @Autowired
    private CachePayConfigService cachePayConfigService;

    @Autowired
    private MerchantSharingProfitService merchantSharingProfitService;
    @Autowired
    private CacheCaInfoService cacheCaInfoService;

    @Autowired
    private UserDataPermissionService userDataPermissionService;

    @Lazy
    @Autowired
    private KuaiDi100Service kuaiDi100Service;
    @Autowired
    private LogisticsOrderService logisticsOrderService;
    @Lazy
    @Autowired
    private UserPurchaseCaService userPurchaseCaService;
    @Value("${sys.fileExportPath:/data/file/campus-admin/}")
    private String fileExportPath;
    @Lazy
    @Autowired
    private CaCollectService caCollectService;
    @Lazy
    @Autowired
    private PlatformOtherActivityService platformOtherActivityService;

    public static List<String> dP = new ArrayList<>();
    public static List<String> logisticsCompany = new ArrayList<>();
    private String ORDER_COUNT = "com.luyou.order....count.query:%s";

    static {
        dP.add("北京市");
        dP.add("上海市");
        dP.add("天津市");
        dP.add("重庆市");
    }

    static {
        logisticsCompany.add("邮政");
    }

    @Override
    public Page<PaperCaOrderResponse> paperCaOrderList(OrderRequest request) {
        boolean choiced = false;
        PageRequest pageRequest = PageRequest.of(request.getPageNo() - 1, request.getPageSize());
        UserDataPermission req = new UserDataPermission();
        req.setUserId(request.getUserId());
        List<UserDataPermission> datas = userDataPermissionService.list(req);
        if (CollectionUtils.isEmpty(datas) || CollectionUtils.isEmpty(datas.get(0).getActivityId())) {
            return PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> 0L);
        }
        Set<String> activityIdSet = datas.get(0).getActivityId().stream().collect(Collectors.toSet());
        Query query = new Query();
        if (StringUtils.isNotBlank(request.getActivityId())) {
            if (activityIdSet.contains(request.getActivityId())) {
                query.addCriteria(Criteria.where("activityId").is(request.getActivityId()));
                choiced = true;
            }
        } else {
            query.addCriteria(Criteria.where("activityId").in(activityIdSet));
        }
        if (StringUtils.isNotBlank(request.getOrderNo())) {
            query.addCriteria(Criteria.where("orderNo").is(request.getOrderNo()));
            choiced = true;
        }
        if (StringUtils.isNotBlank(request.getName())) {
            query.addCriteria(Criteria.where("name").is(request.getName()));
            choiced = true;
        }
        query.addCriteria(Criteria.where("status").ne("0"));
        long count = 0L;
        if (choiced) {
            count = this.mongoTemplate.count(query, OrderInfo.class);
        } else {
            count = 100L;
        }
        Long total = count;
        if (total == 0) {
            return PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> total);
        }
        Sort sort = Sort.by(Sort.Direction.DESC, "payTime");
        query.with(sort);
        List<OrderInfo> orderList = mongoTemplate.find(query.with(pageRequest), OrderInfo.class);
        List<PaperCaOrderResponse> result = orderList.stream().map(orderInfo -> {
            PaperCaOrderResponse paperCaOrder = new PaperCaOrderResponse();
            paperCaOrder.setOrderNo(orderInfo.getOrderNo());
            paperCaOrder.setPayTime(orderInfo.getPayTime());
            paperCaOrder.setTitle(orderInfo.getTitle());
            paperCaOrder.setActivityId(orderInfo.getActivityId());
            paperCaOrder.setName(orderInfo.getSignUpName());
            paperCaOrder.setStatus(orderInfo.getStatus());
            paperCaOrder.setRefundStatus(orderInfo.getRefundStatus());
            paperCaOrder.setUniversityName(orderInfo.getUniversityName());
            paperCaOrder.setTotalFee(orderInfo.getTotalFee());
            ActivityInfo activityInfo = activityService.findOne(orderInfo.getActivityId());
            if (Objects.nonNull(activityInfo)) {
                paperCaOrder.setActivityName(activityInfo.getName());
            }
            SharingProfitOrderDetail sharingProfitOrderDetail =
                    merchantSharingProfitService.getSharingProfitAmountByOrderNo(orderInfo.getOrderNo());
            if (Objects.nonNull(sharingProfitOrderDetail)) {
                paperCaOrder.setSharingProfitStatus(sharingProfitOrderDetail.getSharingProfitStatus());
                Integer sharingProfitAmount = sharingProfitOrderDetail.getSharingProfitAmount();
                paperCaOrder.setSharingProfitAmount(sharingProfitAmount);
            } else {
                paperCaOrder.setSharingProfitStatus(5);
            }
            return paperCaOrder;
        }).collect(Collectors.toList());
        return PageableExecutionUtils.getPage(result, pageRequest, () -> total);
    }

    @Override
    public Page<OrderInfo> getUserOrderPage(OrderRequest request) {
        boolean noChoice = true;
        Query query = (Query) this.getOrderQuery(request, noChoice).get("query");
        query.addCriteria(Criteria.where("deleted").ne(Boolean.TRUE));
        Long count = 0L;
        log.info(":>>> 订单列表条件是否选择:{}", noChoice);
        noChoice = (boolean) this.getOrderQuery(request, noChoice).get("noChoice");
        if (noChoice) {
            count = this.getOrderCount();
            if (Objects.isNull(count)) {
                count = mongoTemplate.count(query, OrderInfo.class);
                if (Objects.nonNull(count)) {
                    this.setOrderCount(count);
                }

            }
        } else {
            count = mongoTemplate.count(query, OrderInfo.class);
        }
        if (Objects.nonNull(count) && count.compareTo(5000L) == 1) {
            log.info(":>>> 总数量:{} 大于5000设置为5000", count);
            count = 5000L;
        }
        log.info(":>>> 订单的数量:{}，查询条件:{}", count, JSON.toJSON(query));
        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "payTime"));
        Sort sort = Sort.by(Sort.Direction.DESC, "payTime");
        query.with(sort);
        List<OrderInfo> orderPOS = mongoTemplate.find(query.with(pageRequest), OrderInfo.class);
        orderPOS.forEach(orderInfo -> {
            SharingProfitOrderDetail sharingProfitOrderDetail =
                    merchantSharingProfitService.getSharingProfitAmountByOrderNo(orderInfo.getOrderNo());
            if (Objects.nonNull(sharingProfitOrderDetail)) {
                orderInfo.setSharingProfitStatus(sharingProfitOrderDetail.getSharingProfitStatus());
                Integer sharingProfitAmount = sharingProfitOrderDetail.getSharingProfitAmount();
                orderInfo.setSharingProfitAmount(sharingProfitAmount);
            } else {
                orderInfo.setSharingProfitStatus(5);
            }
            OrderCommentInfo orderCommentInfo = new OrderCommentInfo();
            orderCommentInfo.setOrderInfoId(orderInfo.getId());
            List<OrderCommentInfo> comments = getComments(orderCommentInfo);
            if (CollectionUtils.isNotEmpty(comments)) {
                orderInfo.setOrderComment(comments.get(0).getComment());
            }

        });
        final Long c = count;
        List<OrderInfo> fiters = new ArrayList<>();
        for (OrderInfo orderInfo : orderPOS) {
            if (!(request.getOptUserName().equals("zhuhuaiqi") || request.getOptUserName().equals("chenhaonan")) && "67db7258121ae3418db9c7b0".equals(orderInfo.getActivityId())) {
                continue;
            }
            fiters.add(orderInfo);
        }
        return PageableExecutionUtils.getPage(fiters, pageRequest, () -> c);
    }

    private HashMap<String, Object> getOrderQuery(OrderRequest request, boolean noChoice) {
        HashMap<String, Object> res = new HashMap<>();
        Query query = new Query();
        Criteria criteriaPay = null;
        if (StringUtils.isNotBlank(request.getStatus())) {
            query.addCriteria(Criteria.where("status").is(request.getStatus()));
            noChoice = false;
        } else if (CollectionUtils.isNotEmpty(request.getStatuses())) {
            query.addCriteria(Criteria.where("status").in(request.getStatuses()));
            noChoice = false;
        } else if (CollectionUtils.isNotEmpty(request.getNotStatuses())) {
            query.addCriteria(Criteria.where("status").nin(request.getNotStatuses()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getActivityId())) {
            query.addCriteria(Criteria.where("activityId").is(request.getActivityId()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getUniversityId())) {
            query.addCriteria(Criteria.where("universityId").is(request.getUniversityId()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getOrderNo())) {
//            Pattern pattern = Pattern.compile("^.*" + request.getOrderNo() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("orderNo").is(request.getOrderNo()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getMobile())) {
//            Pattern pattern = Pattern.compile("^.*" + request.getMobile() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("mobile").is(request.getMobile()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getName())) {
//            Pattern pattern = Pattern.compile("^.*" + request.getName() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("name").is(request.getName()));
            noChoice = false;
        }
        if (Objects.nonNull(request.getVerifyStatus())) {
            query.addCriteria(Criteria.where("verifyStatus").is(request.getVerifyStatus()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getTagsSearchStr())) {
            Pattern pattern = Pattern.compile("^.*" + request.getTagsSearchStr() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("tagsSearchStr").regex(pattern));
            noChoice = false;
        }
        if (request.getStartTime() != null || request.getEndTime() != null) {
            noChoice = false;
            criteriaPay = Criteria.where("payTime");
            if (request.getStartTime() != null) {
                criteriaPay.gte(request.getStartTime());
            }
            if (request.getEndTime() != null) {
                criteriaPay.lte(request.getEndTime());
            }
        }
        if (!"0".equals(request.getRefundStatus()) && StringUtils.isNotBlank(request.getRefundStatus())) {
            query.addCriteria(Criteria.where("refundStatus").is(request.getRefundStatus()));
            noChoice = false;
        }
//        if (CollectionUtils.isNotEmpty(request.getStatuses())) {
//            query.addCriteria(Criteria.where("status").in(request.getStatuses()));
//        }
        if (StringUtils.isNotBlank(request.getTransationId())) {
//            Pattern pattern = Pattern.compile("^.*" + request.getTransactionId() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("transactionId").is(request.getTransationId()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getLogisticsNo())) {
            List<String> logisticsNoList = Arrays.asList(request.getLogisticsNo());
//            Pattern pattern = Pattern.compile("^.*" + request.getLogisticsNo() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("logisticsNos").in(logisticsNoList));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getSignUpName())) {
            query.addCriteria(Criteria.where("signUpName").is(request.getSignUpName()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getSignUpMobile())) {
            query.addCriteria(Criteria.where("signUpMobile").is(request.getSignUpMobile()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getRefundApplyUserType())) {
            query.addCriteria(Criteria.where("refundApplyUserType").is(request.getRefundApplyUserType()));
            noChoice = false;
        }
        if (Objects.nonNull(criteriaPay)) {
            query.addCriteria(criteriaPay);
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getRefundWay())) {
            query.addCriteria(Criteria.where("refundWay").is(request.getRefundWay()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getRefundPayChannel())) {
            query.addCriteria(Criteria.where("refundPayChannel").is(request.getRefundPayChannel()));
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getCategory())) {
            if ("ca".equals(request.getCategory())) {
                query.addCriteria(Criteria.where("category").is(null));
            } else {
                query.addCriteria(Criteria.where("category").is(request.getCategory()));
            }
            noChoice = false;
        }
        if (StringUtils.isNotBlank(request.getAppId())) {
            query.addCriteria(Criteria.where("appId").is(request.getAppId()));
            noChoice = false;
        }
        if (Objects.nonNull(request.getStartRefundTime()) && Objects.nonNull(request.getEndRefundTime())) {
            query.addCriteria(Criteria.where("refundTime").gte(request.getStartRefundTime()).lte(request.getEndRefundTime()));
            noChoice = false;
        }
        log.info(":>>> 是否选择:{}", noChoice);
        res.put("query", query);
        res.put("noChoice", noChoice);
        log.info(":>>> 订单查询的条件:{}", JSON.toJSONString(res));
        return res;
    }


    @Override
    public Map<String, Object> orderImport(byte[] inputStream, String fileName, String activityId, boolean sendMsg, String mode) {
        log.info("orderImport fileName {}", fileName);
        try {
            Map<String, Object> result = new HashMap<>();
            List<OrderImport> models = ExcelUtil.readData(new ByteArrayInputStream(inputStream), OrderImport.class);
            result.put("allCount", models.size());
            int matchCount = 0;
            int notMatchCount = 0;
            int errorInfo = 0;
            List<Integer> notMatchRows = new ArrayList<>();
            for (int i = 0; i < models.size(); i++) {
                OrderImport model = models.get(i);
                log.info(":>>> 订单号 {} 子订单号:{} 物流单号:{} 物流公司:{}", model.getOrderNo(), model.getSuborderNo(),
                        model.getLogisticsNo(), model.getLogisticsCompany());
                if (StringUtils.isBlank(model.getOrderNo()) || StringUtils.isBlank(model.getLogisticsNo())
                        || StringUtils.isBlank(model.getLogisticsCompany()) || StringUtils.isBlank(model.getSuborderNo())) {
                    log.error(":>>> 导入参数错误:订单编号、子订单编号为空、物流单号、物流公司为空");
                    errorInfo++;
                    continue;
                }
                if (StringUtils.isBlank(model.getFrom())) {
                    log.error(":>>> 发货地址不能为空");
                    throw new BusinessException("发货地址不能为空");
                }
                boolean r = checkShipInfo(model.getOrderNo(), model.getLogisticsNo(), model.getLogisticsCompany());
                if (!r) {
                    log.error(":>>> 检查物流信息参数错误:订单编号、物流单号、物流公司为空,参数错误");
                    errorInfo++;
                    continue;
                }
                Query query = new Query();
                query.addCriteria(Criteria.where("orderNo").is(model.getOrderNo()));
                if (StringUtils.isNotBlank(activityId)) {
                    query.addCriteria(Criteria.where("activityId").is(activityId));
                }
                /**
                 * 状态,0:待付款,1:已付款,2:制作中,3:待发货,4:待收货,5:已收货,6:订单完成,7:订单关闭,8:售后中,9:退款中,10:部分已发货
                 */
                String[] statuses = {"1", "2", "3", "4", "8", "10"};
                query.addCriteria(Criteria.where("status").in(statuses));
                List<OrderInfo> orderInfos = mongoTemplate.find(query, OrderInfo.class);
                if (CollectionUtils.isEmpty(orderInfos)) {
                    log.error(":>>> 用户订单不存在:{}", model.getOrderNo());
                    notMatchCount++;
                    continue;
                }
                for (OrderInfo orderInfo : orderInfos) {

                    orderInfo.setLogisticsNo(model.getLogisticsNo());
                    orderInfo.setLogisticsCompany(model.getLogisticsCompany());
                    orderInfo.setSendMsg(sendMsg);
                    orderInfo.setFrom(model.getFrom());
                    if ("4".equals(orderInfo.getStatus()) && !model.getLogisticsNo().equals(orderInfo.getLogisticsNo())) {
                        String lTips =
                                "您的订单物流单号已经更新,请按照新单号查询,旧物流单号:" + orderInfo.getLogisticsNo() + ",物流公司:" + orderInfo.getLogisticsCompany();
                        orderInfo.setLogisticsTips(lTips);
                    }
                    List<String> subOrderNo = new ArrayList<>();
                    subOrderNo.add(model.getSuborderNo());
                    orderInfo.setSubOrderNos(subOrderNo);
                    orderInfo.setPostSale(model.getPostSale());
                    if (StringUtils.isNotBlank(model.getChildItemId1())) {
                        orderInfo.getChildItemIds().add(model.getChildItemId1());
                    }
                    if (StringUtils.isNotBlank(model.getChildItemId2())) {
                        orderInfo.getChildItemIds().add(model.getChildItemId2());
                    }
                    if (StringUtils.isNotBlank(model.getChildItemId3())) {
                        orderInfo.getChildItemIds().add(model.getChildItemId3());
                    }
                    if (StringUtils.isNotBlank(model.getChildItemId4())) {
                        orderInfo.getChildItemIds().add(model.getChildItemId4());
                    }
                    if (StringUtils.isNotBlank(model.getChildItemId5())) {
                        orderInfo.getChildItemIds().add(model.getChildItemId5());
                    }
                    if (StringUtils.isNotBlank(model.getChildItemId6())) {
                        orderInfo.getChildItemIds().add(model.getChildItemId6());
                    }
                    orderInfo.setMode(mode);
                    this.shipping(orderInfo);
                    matchCount++;
                }
            }
            if (errorInfo == models.size()) {
                log.error(":>>> 发货信息错误 ，发货失败");
                throw new BusinessException("发货信息错误 ，发货失败");

            }
            result.put("matchCount", matchCount);
            result.put("notMatchCount", notMatchCount);
            result.put("notMatchRows", notMatchRows);
            result.put("errorInfo", errorInfo);
            result.put("tips", "列序号从0(A列)开始,第1列订单编号(A列)、第2列(B列)物流公司、第3列(C列)物流单号不能为空!");
            return result;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("orderImport error fileName {}", fileName, e);
            return null;
        }
    }

    @Override
    public Map<String, Object> reDoOrder(byte[] inputStream, String fileName, String activityId, String batchId) {
        log.info("reDoOrder fileName {}", fileName);
        Date date = new Date();
        try {
            Map<String, Object> result = new HashMap<>();
            List<ReDoOrderImport> models = ExcelUtil.readData(new ByteArrayInputStream(inputStream), ReDoOrderImport.class);
            result.put("allCount", models.size());
            int matchCount = 0;
            int notMatchCount = 0;
            int errorInfo = 0;
            List<Integer> notMatchRows = new ArrayList<>();
            for (int i = 0; i < models.size(); i++) {
                ReDoOrderImport model = models.get(i);
                log.info(":>>> 订单号 {} 子订单号:{}", model.getOrderNo(), model.getSubOrderNo());
                if (StringUtils.isBlank(model.getOrderNo()) || StringUtils.isBlank(model.getSubOrderNo())) {
                    log.error(":>>> 导入参数错误:订单编号、子订单编号为空");
                    errorInfo++;
                    continue;
                }
                Query query = new Query();
                query.addCriteria(Criteria.where("orderNo").is(model.getOrderNo()));
                if (StringUtils.isNotBlank(activityId)) {
                    query.addCriteria(Criteria.where("activityId").is(activityId));
                }
                Update updateOrder = new Update();
                updateOrder.set("reDoBatchId", batchId);
                updateOrder.set("updatedTime", date);
                UpdateResult updateOrderResult = mongoTemplate.updateFirst(query, updateOrder, OrderInfo.class);
                log.info(":>>> 修改订单:{},数量为:{}", model.getOrderNo(), updateOrderResult.getModifiedCount());
                query.addCriteria(Criteria.where("oOrderNo").is(model.getSubOrderNo()));
                Update update = new Update();
                update.set("realed", Boolean.TRUE);
                update.set("reDoBatchId", batchId);
                update.set("updatedTime", date);
                UpdateResult updateResult = mongoTemplate.updateMulti(query, update, OOrderInfo.class);
                log.info(":>>> 修改子订单:{},数量为:{}", model.getSubOrderNo(), updateResult.getModifiedCount());
                // 处理增品子订单
                this.reDoSubOrder(model.getOrderNo(), model.getSubOrderNo(), batchId, date);
                matchCount++;
            }
            if (errorInfo == models.size()) {
                log.error(":>>> 发货信息错误 ，发货失败");
                throw new BusinessException("发货信息错误 ，发货失败");
            }
            result.put("matchCount", matchCount);
            result.put("notMatchCount", notMatchCount);
            result.put("notMatchRows", notMatchRows);
            result.put("errorInfo", errorInfo);
            result.put("tips", "列序号从0(A列)开始,第1列订单编号(A列)、第2列(B列)物流公司、第3列(C列)物流单号不能为空!");
            return result;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("orderImport error fileName {}", fileName, e);
            return null;
        }
    }

    @Override
    public Map<String, Object> batchDoRefund(byte[] inputStream, String fileName, String optName) {
        log.info(":>>> 开始处理批量退款:{}", optName);
        try {
            Map<String, Object> result = new HashMap<>();
            List<OrderBatchRefundImport> models = ExcelUtil.readData(new ByteArrayInputStream(inputStream),
                    OrderBatchRefundImport.class);
            result.put("allCount", models.size());
            int matchCount = 0;
            int notMatchCount = 0;
            int errorInfo = 0;
            List<Integer> notMatchRows = new ArrayList<>();
            for (int i = 0; i < models.size(); i++) {
                OrderBatchRefundImport model = models.get(i);
                log.info(":>>> 开始批量退款:{}", model.getOrderNo());
                Query query = new Query().addCriteria(Criteria.where("orderNo").is(model.getOrderNo()));
                OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
                if (Objects.isNull(orderInfo)) {
                    log.error(":>>> 订单:{} 不存在", model.getOrderNo());
                    notMatchCount++;
                    continue;
                }
                OrderRefundOptVO pre = new OrderRefundOptVO();
                pre.setId(orderInfo.getId());
                Query querySub = new Query().addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()).and(
                        "gifted").ne(Boolean.TRUE));
                List<OOrderInfo> sub = mongoTemplate.find(querySub, OOrderInfo.class);
                Integer refundFee = 0;
                HashMap<String, Integer> subMap = new HashMap<>();
                for (OOrderInfo s : sub) {
                    subMap.put(s.getOOrderNo(), s.getSalePrice());
                    refundFee = refundFee + s.getSalePrice();
                }
                pre.setSubOrders(subMap);
                pre.setRefundFee(refundFee);
                preRefund(pre);

                OrderRefundOptVO req = new OrderRefundOptVO();
                req.setId(orderInfo.getId());
                req.setVerifyStatus(2);
                req.setRefundDesc("批量退款");
                req.setOptName(optName);
                req.setRefundWay("on-line");
                req.setRefundPayChannel("微信");
                doRefund(req);
                matchCount++;


            }
            result.put("matchCount", matchCount);
            result.put("notMatchCount", notMatchCount);
            result.put("notMatchRows", notMatchRows);
            result.put("errorInfo", errorInfo);
            result.put("tips", "列序号从0(A列)开始,第1列订单编号(A列)、第2列(B列)物流公司、第3列(C列)物流单号不能为空!");
            return result;
        } catch (Exception e) {
            log.error("orderImport error fileName {}", fileName, e);
            return null;
        }
    }

    @Override
    public boolean addressUpdate(OrderUpdateRequest request) {
        log.info("修改订单收货地址开始,参数:{}", JSON.toJSONString(request));
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(request.getId()));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        UserCaRecord userCaRecord = new UserCaRecord();
        Update update = new Update();
        String toMobile = "";
        String universityId = "";
        String universityName = "";
        if (StringUtils.isNotBlank(request.getAddress())) {
            update.set("address", request.getAddress());
        }
        if (StringUtils.isNotBlank(request.getName())) {
            update.set("name", request.getName());
        }
        if (StringUtils.isNotBlank(request.getCaPrintName())) {
            update.set("caPrintName", request.getCaPrintName());
            userCaRecord.setCaName(request.getCaPrintName());
        }
        if (StringUtils.isNotBlank(request.getMobile())) {
            update.set("mobile", request.getMobile());
            toMobile = request.getMobile();
        }
        if (StringUtils.isNotBlank(request.getProvince())) {
            update.set("province", request.getProvince());
        }
        if (StringUtils.isNotBlank(request.getCity())) {
            update.set("city", request.getCity());
        }
        if (StringUtils.isNotBlank(request.getArea())) {
            update.set("area", request.getArea());
        }
        if (StringUtils.isNotBlank(request.getUniversityId())) {
            update.set("universityId", request.getUniversityId());
            Query query1 = new Query().addCriteria(Criteria.where("id").is(request.getUniversityId()));
            UniversityInfo universityInfo = mongoTemplate.findOne(query1, UniversityInfo.class);
            if (Objects.nonNull(universityInfo)) {
                update.set("universityName", universityInfo.getName());
                userCaRecord.setUniversityName(universityInfo.getName());
                universityId = request.getUniversityId();
                universityName = universityInfo.getName();
            }
        }
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, OrderInfo.class);
        if (updateResult.getModifiedCount() > 0) {
            log.info("订单收货地址信息修改成功");
            CreateCaOrderTagVO req = new CreateCaOrderTagVO();
            req.setId(request.getId());
            req.setTag("修改地址信息");
            createTags(req);
            String orderNo = orderInfo.getOrderNo();
            query = new Query();
            // query.addCriteria(Criteria.where(""))
            platformOtherActivityService.updateByMobileAndActivityId(orderInfo.getMobile(),
                    toMobile, orderInfo.getActivityId(), request.getCaPrintName(), universityId,
                    universityName, orderInfo.getAccountInfoId());
            userCaRecordService.updateByMobileAndActivityId(orderInfo.getMobile(),
                    toMobile, orderInfo.getActivityId(), request.getCaPrintName(), universityId,
                    universityName);
        }
        Query querySubOrder = new Query().addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()));
        List<OOrderInfo> subOrderInfos = mongoTemplate.find(querySubOrder, OOrderInfo.class);
        if (CollectionUtils.isNotEmpty(subOrderInfos)) {
            for (OOrderInfo subOrderInfo : subOrderInfos) {
                log.info(":>>> 开始修改订单:{} 电子证书:{},数据:{}", orderInfo.getOrderNo(), subOrderInfo.getCertificateNo(),
                        JSON.toJSON(userCaRecord));
                userCaRecordService.update(subOrderInfo.getCertificateNo(), userCaRecord);
            }
        }
        if (updateResult.getModifiedCount() > 0) {
            DingTalkRobotRequest dingTalkRobotRequest = new DingTalkRobotRequest();
            dingTalkRobotRequest.setOptUser(request.getOptUser());
            dingTalkRobotRequest.setTitle(request.getSourcePlatform());
            dingTalkRobotRequest.setContent(orderInfo.getOrderNo());
            dingTalkRobotRequest.setModel("订单-修改订单");
            dingTalkService.sendBusniessDingTalkMarkdownMsg(dingTalkRobotRequest);
        }
        //TODO: activity_user_record,活动用户数待更新

        return true;
    }

    @Override
    public List<String> createTags(CreateCaOrderTagVO req) {
        log.info(":>>> 添加证书订单标签:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getId()) || StringUtils.isBlank(req.getTag())) {
            log.error(":>>> 添加证书标签参数错误");
            throw new BusinessException("参数错误");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(orderInfo)) {
            log.error(":>>> 证书订单:{} 不存在", req.getId());
            throw new BusinessException("数据不存在");
        }
        if (orderInfo.getTags().contains(req.getTag())) {
            return orderInfo.getTags();
        }
        orderInfo.getTags().add(req.getTag());
        if (StringUtils.isBlank(orderInfo.getTagsSearchStr())) {
            orderInfo.setTagsSearchStr(req.getTag());
        } else {
            orderInfo.setTagsSearchStr(orderInfo.getTagsSearchStr() + "," + req.getTag());
        }
        Update update = new Update();
        update.set("tags", orderInfo.getTags());
        update.set("tagsSearchStr", orderInfo.getTagsSearchStr());
        update.set("updatedTime", new Date());
        mongoTemplate.updateFirst(query, update, OrderInfo.class);
        return orderInfo.getTags();
    }

    @Override
    public List<String> deleteTags(CreateCaOrderTagVO req) {
        log.info(":>>> 删除证书订单标签:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getId()) || StringUtils.isBlank(req.getTag())) {
            log.error(":>>> 删除证书标签参数错误");
            throw new BusinessException("参数错误");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(orderInfo)) {
            log.error(":>>> 证书订单:{} 不存在", req.getId());
            throw new BusinessException("数据不存在");
        }
        if (orderInfo.getTags().contains(req.getTag())) {
            List<String> t = orderInfo.getTags();
            t.remove(req.getTag());
            if (Objects.isNull(t)) {
                t = new ArrayList<String>();
            }
            Update update = new Update();
            update.set("tags", t);
            update.set("tagsSearchStr", orderInfo.getTagsSearchStr().replace(req.getTag(), ""));
            update.set("updatedTime", new Date());
            mongoTemplate.updateFirst(query, update, OrderInfo.class);

            return orderInfo.getTags();
        }
        return orderInfo.getTags();
    }

    @Override
    public boolean createComment(OrderCommentInfo req) {
        log.info(":>>> 开始创建订单备注:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getComment()) || StringUtils.isBlank(req.getOrderInfoId())) {
            log.error(":>>> 创建备注错误,参数错误");
            throw new BusinessException("参数错误");
        }
        req.setCreatedTime(new Date());
        req.setStatus(Boolean.FALSE);
        req.setOptName(req.getOptName());
        mongoTemplate.insert(req);
        return true;
    }

    @Override
    public OrderInfo findOne(String id) {
        log.info(":>>> 开始获取订单详情:{}", id);
        if (StringUtils.isBlank(id)) {
            log.error(":>>> 订单ID为空:{}", id);
            throw new BusinessException("订单ID为空");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(orderInfo)) {
            log.error(":>>> 订单不存在:{}", id);
            throw new BusinessException("订单不存在");
        }
        Query querySubOrder = new Query().addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()));
        List<OOrderInfo> subOrder = mongoTemplate.find(querySubOrder, OOrderInfo.class);
        for (OOrderInfo oOrderInfo : subOrder) {
            if (Objects.isNull(oOrderInfo.getPayPrice())) {
                oOrderInfo.setPayPrice(oOrderInfo.getItemPrice());
            }
            if (StringUtils.isNotBlank(oOrderInfo.getItemInfoId())) {
                Query query1 = new Query().addCriteria(Criteria.where("id").is(oOrderInfo.getItemInfoId()));
                CaInfo caInfo = mongoTemplate.findOne(query1, CaInfo.class);
                if (Objects.nonNull(caInfo)) {
                    oOrderInfo.setLevel(caInfo.getLevel());
                    oOrderInfo.setEdition(caInfo.getEdition());
                    orderInfo.setLevel(caInfo.getLevel());
                    orderInfo.setEdition(caInfo.getEdition());
                }
            }
        }
        orderInfo.setOOrderInfos(subOrder);
        if (!org.springframework.util.CollectionUtils.isEmpty(subOrder)) {
            String s = "";
            String oOrderNo = "";
            /**
             * 状态,0:待付款,1:已付款,2:制作中,3:待发货,4:待收货,5:已收货,6:订单完成,7:订单关闭,8:售后中,9:部分已发货
             */
            for (OOrderInfo oOrderInfo : subOrder) {
                if ("4".equals(oOrderInfo.getStatus())) {
                    s = "4";
                    oOrderNo = oOrderInfo.getOOrderNo();
                    break;
                }
            }
            if ("4".equals(s)) {
                log.info(":>>> 订单:{} 子订单:{},已经发货,标记主订单为已经发货", orderInfo.getOrderNo(), oOrderNo);
                if ("1".equals(orderInfo.getStatus()) || "2".equals(orderInfo.getStatus()) || "3".equals(orderInfo.getStatus())) {
                    orderInfo.setStatus("4");
                }
            }
        }
        orderInfoTipService.setSubOrderTips(orderInfo);
        List<SharingProfitOrderDetail> list = merchantSharingProfitService.getSharingProfitListByOrderNo(orderInfo.getOrderNo());
        if (CollectionUtils.isEmpty(list)) {
            orderInfo.setSharingProfitStatus(5);
        } else {
            SharingProfitOrderDetail sharingProfitOrderDetail = list.get(0);
            Integer sharingProfitAmount = list.stream().mapToInt(SharingProfitOrderDetail::getSharingProfitAmount).sum();
            orderInfo.setSharingProfitAmount(sharingProfitAmount);
            orderInfo.setSharingProfitStatus(sharingProfitOrderDetail.getSharingProfitStatus());
        }
        return orderInfo;
    }

    @Override
    public List<OrderCommentInfo> getComments(OrderCommentInfo req) {
        log.info("::>> 获取订单备注:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getOrderInfoId())) {
            log.error(":>>> 获取备注错误,参数错误");
            throw new BusinessException("参数错误");
        }
        Query query = new Query().addCriteria(Criteria.where("orderInfoId").is(req.getOrderInfoId()));
        query.with(Sort.by(Sort.Order.desc("createdTime")));
        return mongoTemplate.find(query, OrderCommentInfo.class);
    }

    @Override
    public boolean shipping(OrderInfo req) {
        log.info(":>>> 开始发货:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getId()) || StringUtils.isBlank(req.getLogisticsNo())
                || StringUtils.isBlank(req.getLogisticsCompany()) || CollectionUtils.isEmpty(req.getSubOrderNos())) {

            log.error(":>>> 发货参数错误");
            throw new BusinessException("发货参数错误");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(orderInfo)) {
            log.error(":>>> 订单不存在:{}", req.getId());
            throw new BusinessException("订单不存在");
        }
        /**
         * 状态,0:待付款,1:已付款,2:制作中,3:待发货,4:待收货,5:已收货,6:订单完成,7:订单关闭,8:售后中,9:退款中,10:待返货，11:返货中，12:退款完成
         */
        if (orderInfo.getStatus().equals("6") || orderInfo.getStatus().equals("7")
                || orderInfo.getStatus().equals("9") || orderInfo.getStatus().equals("12")) {
            log.error(":>>> 订单状态:{},是[订单完成,订单关闭,退款中,退款完成]", orderInfo.getStatus());
            throw new BusinessException("订单状态错误");
        }
        String from = req.getFrom();
        if (Objects.nonNull(from)) {
            if (from.contains("[")) {
                from = from.replaceAll("\\[", "");
            }
            if (from.contains("]")) {
                from = from.replaceAll("]", "");
            }
        }
        Date date = new Date();
        Update update = new Update();
        update.set("status", "4");
        update.set("logisticsNo", req.getLogisticsNo());
        update.push("logisticsNos", req.getLogisticsNo());
        update.set("logisticsCompany", req.getLogisticsCompany());
        update.set("from", from);
        update.set("shippingTime", date);
        update.set("tips", "你的订单已发货，请注意查收，可点击下方按钮查看物流详情，若查看不到物流详情，是因为还在扫描出库中，请耐心等待3-5天后再次点击查看！");
        if (orderInfo.getStatus().equals("4") && Boolean.TRUE.equals(req.getPostSale())) {
            log.info(":>>> 订单:{} 已经是已发货状态,属于补发订单", orderInfo.getOrderNo());
            update.set("logisticsTips", req.getLogisticsTips());
        }
        update.set("updatedTime", date);
        UpdateResult result = mongoTemplate.updateFirst(query, update, OrderInfo.class);
        boolean re = result.getModifiedCount() > 0 ? true : false;
        log.info(":>>> 订单:{} 发货状态为:{}", req.getId(), re);
        Query querySubOrder = new Query().addCriteria(Criteria.where("oOrderNo").in(req.getSubOrderNos()));
        List<OOrderInfo> subOrderInfos = mongoTemplate.find(querySubOrder, OOrderInfo.class);
        log.info(":>>> 子订单:{} 数量:{}", JSON.toJSONString(req.getSubOrderNos()), subOrderInfos == null ? 0 :
                subOrderInfos.size());
        if (!CollectionUtils.isEmpty(subOrderInfos)) {
            for (OOrderInfo subOrderInfo : subOrderInfos) {
                log.info(":>>> 子订单:{},物流编号:{}", subOrderInfo.getOOrderNo(), subOrderInfo.getLogisticsNo());
                Query query1 = new Query().addCriteria(Criteria.where("id").is(subOrderInfo.getId()));
                if (StringUtils.isBlank(subOrderInfo.getLogisticsNo()) || !req.getLogisticsNo().equals(subOrderInfo.getLogisticsNo())) {
                    UpdateResult updateResultSub = mongoTemplate.updateFirst(query1, update, OOrderInfo.class);
                    log.info(":>>> 更新子订单:{},结果为:{}", subOrderInfo.getId(), updateResultSub.getModifiedCount());
                    if (updateResultSub.getModifiedCount() > 0 ? true : false) {
                        LogisticsOrderDto da = new LogisticsOrderDto();
                        da.setOrderNo(orderInfo.getOrderNo());
                        da.setSubOrderNo(subOrderInfo.getOOrderNo());
                        da.setItemInfoId(subOrderInfo.getItemInfoId());
                        da.setLogisticsNo(req.getLogisticsNo());
                        da.setLogisticsCompany(req.getLogisticsCompany());
                        da.setShippingTime(date);
                        da.setChildItemIds(req.getChildItemIds());
                        try {
                            logisticsOrderService.handle(da, req.getMode());
                        } catch (Exception e) {
                            log.error(":>>> 处理物流订单错误:{}", e);
                        }

                    }
                    //订单订阅
                    String address = orderInfo.getProvince() + orderInfo.getCity() + orderInfo.getArea() + orderInfo.getAddress();
                    KuaiDi100PollMapBodyDTO dto =
                            KuaiDi100PollMapBodyDTO.builder().
                                    number(req.getLogisticsNo()).
                                    to(address).
                                    orderNo(orderInfo.getOrderNo())
                                    .subOrderNo(subOrderInfo.getOOrderNo())
                                    .phone(orderInfo.getMobile())
                                    .from(from)
                                    .logisticsCompany(req.getLogisticsCompany()).
                                    build();
                    kuaiDi100Service.pushRollMap(dto);
                } else {
                    // 避免物流单号重复
                    if (!req.getLogisticsNo().equals(subOrderInfo.getLogisticsNo())) {
                        Update update1 = new Update();
                        update1.set("status", "4");
                        update1.set("shippingTime", date);
                        update1.set("from", from);
                        update1.set("logisticsNo", req.getLogisticsNo());
                        update1.set("postSaleStatus", "1");
                        update1.set("postSaleLogisticsCompany", req.getLogisticsCompany());
                        update1.set("postSaleLogisticsNo", req.getLogisticsNo());
                        UpdateResult updateResultSub = mongoTemplate.updateFirst(query1, update1, OOrderInfo.class);
                        log.info(":>>> 更新子订单:{},结果为:{}", subOrderInfo.getId(), updateResultSub.getModifiedCount());
                        //订单订阅
                        String address = orderInfo.getProvince() + orderInfo.getCity() + orderInfo.getArea() + orderInfo.getAddress();
                        KuaiDi100PollMapBodyDTO dto =
                                KuaiDi100PollMapBodyDTO.builder().
                                        number(req.getLogisticsNo()).
                                        to(address).
                                        orderNo(orderInfo.getOrderNo())
                                        .subOrderNo(subOrderInfo.getOOrderNo())
                                        .phone(orderInfo.getMobile())
                                        .from(from)
                                        .logisticsCompany(req.getLogisticsCompany()).
                                        build();
                        kuaiDi100Service.pushRollMap(dto);
                    }
                }

                // 处理统一批次物流单号
                if (StringUtils.isNotBlank(subOrderInfo.getSingleNo())) {
                    Query querySingle =
                            new Query().addCriteria(Criteria.where("singleNo").is(subOrderInfo.getSingleNo()));
                    UpdateResult updateResultSub = mongoTemplate.updateMulti(querySingle, update, OOrderInfo.class);
                    log.info(":>>> 更新子订单:{},同一批次:{} 结果为:{}", subOrderInfo.getId(), subOrderInfo.getSingleNo(),
                            updateResultSub.getModifiedCount());
                }

            }
        }
        if (re && StringUtils.isNotBlank(req.getLogisticsNo()) && !req.getLogisticsNo().equals(orderInfo.getLogisticsNo())) {
            //更新主订单成功
            List<DeliveryOrderSubMsgMQVO> batchShippingOrderList = new ArrayList<>();
            PayConfigPage payConfigPage = cachePayConfigService.findByActivityId(orderInfo.getActivityId());
            if (!StringUtils.isAllBlank(orderInfo.getOrderNo(), req.getLogisticsNo(), req.getLogisticsCompany())) {
                DeliveryOrderSubMsgMQVO deliveryOrderSubMsgMQ = new DeliveryOrderSubMsgMQVO();
                deliveryOrderSubMsgMQ.setOrderNo(orderInfo.getOrderNo());
                deliveryOrderSubMsgMQ.setLogisticsNo(req.getLogisticsNo());
                deliveryOrderSubMsgMQ.setLogisticsCompany(req.getLogisticsCompany());
                if (Objects.nonNull(payConfigPage.getMsgTemplateRemark())) {
                    deliveryOrderSubMsgMQ.setRemark(payConfigPage.getMsgTemplateRemark());
                }
                if (!CollectionUtils.isEmpty(subOrderInfos)) {
                    deliveryOrderSubMsgMQ.setSubOrderNo(subOrderInfos.get(0).getOOrderNo());
                }
                batchShippingOrderList.add(deliveryOrderSubMsgMQ);
            }
            try {
                deliveryOrderSubMsgService.doDeliveryOrderSub(batchShippingOrderList);
            } catch (Exception e) {
                log.error("订单发货订阅消息失败", e);
            }

        }
        if (Boolean.TRUE.equals(req.getSendMsg())) {
            String[] params = new String[3];
            params[0] = "商品";
            params[1] = req.getLogisticsCompany();
            params[2] = req.getLogisticsNo();
            this.sendShipMsg(orderInfo.getMobile(), orderInfo.getActivityId(), params);
        }
        return re;
    }

    @Override
    public String export(OrderRequest req, HttpServletResponse response) {

        log.info(":>>> 开始订单导出:{}", JSON.toJSONString(req));
        HashMap<String, UniversityInfo> universityInfoHashMap = new HashMap<>();
        Query query = (Query) this.getOrderQuery(req, false).get("query");
        Long count = mongoTemplate.count(query, OrderInfo.class);
//        List<OrderInfo> contents = mongoTemplate.find(query, OrderInfo.class);
        log.info(":>>> 订单导出总数量:{}", count);
        if (count.compareTo(0L) == -1) {
            log.error(":>>> 用户 订单为空");
            return "";
        }
        log.info(":>>> 订单发货总量:{}", count);
        FileExportTask fileExportTask = new FileExportTask();
        fileExportTask.setToken(req.getOptUserName());
        fileExportTask.setBizType("order");
        fileExportTask.setStatus(0);
        fileExportTask.setOptUser(req.getOptUserName());
        fileExportTask.setOptUserId(req.getUserId());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(new Date());
        ActivityInfo activityInfo = null;
        if (StringUtils.isNotBlank(req.getActivityId())) {
            Query queryA = new Query().addCriteria(Criteria.where("id").is(req.getActivityId()));
            activityInfo = mongoTemplate.findOne(queryA, ActivityInfo.class);
        }
        String fileName = "证书订单-" + (activityInfo == null ? "" : activityInfo.getName()) + "-" + dateStr;
        String f = fileName + new Date().getTime() + ".xlsx";
        fileExportTask.setFileName(f);
        fileExportTask.setNum(count.intValue());
        fileExportTask.setDesc(activityInfo == null ? "证书订单" : activityInfo.getName() + "证书订单");
        String re = fileExportTaskService.create(fileExportTask);
        SystemOptLog optlog = new SystemOptLog();
        optlog.setIp(req.getIpAddress());
        optlog.setOptUserName(req.getOptUserName());
        optlog.setOptTime(new Date());
        optlog.setBizType("export-order");
        optlog.setOptRealName(req.getOptUserRealName());
        optlog.setSqlDetai(JSON.toJSONString(query, SerializerFeature.IgnoreNonFieldGetter));
        optlog.setDesc("导出证书订单文件名:" + f + ",数据总条数:" + count);
        systemOptLogService.create(optlog);
        this.exportOrder(query, count, f, re);
        return re;
    }

    @Override
    public boolean preRefund(OrderRefundOptVO req) {
        log.info(":>>> 开始退款预操作:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getId()) || Objects.isNull(req.getRefundFee()) || Objects.isNull(req.getSubOrders()) || req.getSubOrders().isEmpty()) {
            log.error(":>>> 退款操作参数错误");
            throw new BusinessException("退款操作参数错误");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(orderInfo)) {
            log.error(":>>> 证书订单不存在:{}", req.getId());
            throw new BusinessException("证书订单不存在");
        }
        Query querySubOrders = new Query().addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()));
        List<OOrderInfo> subOrders = mongoTemplate.find(querySubOrders, OOrderInfo.class);
        if (CollectionUtils.isEmpty(subOrders)) {
            log.error(":>>> 证书订单子订单不存在:{}", req.getId());
            throw new BusinessException("证书订单子订单不存在");
        }
        //状态,0:待付款,1:已付款,2:制作中,3:待发货,4:待收货,5:已收货,6:订单完成,7:订单关闭,8:售后中,9:退款中,10:待返货，11:返货中，12:退款完成
//        退款状态,0:未退款,1:退款申请,2:退款中,3:退款完成,4:待返货 7:部分退款中
        if (orderInfo.getRefundStatus().equals("1") || orderInfo.getRefundStatus().equals("2") || orderInfo.getRefundStatus().equals("3") || orderInfo.getRefundStatus().equals("7")) {
            log.error(":>>> 订单:{} 已经是退款中或退款完成状态", req.getId());
            return true;
        }
        Integer refundFee = 0;
        Integer expressFee = 0;
        List<String> subOrderIds = new ArrayList<>();
        for (String subId : req.getSubOrders().keySet()) {
            for (OOrderInfo oOrderInfo : subOrders) {
                if (Objects.nonNull(orderInfo.getExpressFee())) {
                    expressFee = orderInfo.getExpressFee() + orderInfo.getExtraExpressFee() / subOrders.size();
                }
                if (subId.equals(oOrderInfo.getOOrderNo())) {
                    if (req.getSubOrders().get(subId).compareTo(oOrderInfo.getSalePrice() + orderInfo.getExtraExpressFee() + (orderInfo.getExpressFee() == null ? 0 : orderInfo.getExpressFee())) == 1) {
                        log.error(":>>> 子订单:{} 金额:{} 大于付款金额", subId, req.getSubOrders().get(subId),
                                oOrderInfo.getSalePrice());
                        throw new BusinessException("子订单退款金额异常");
                    }
                    refundFee = refundFee + req.getSubOrders().get(subId) + expressFee;
                }

            }
            subOrderIds.add(subId);
        }
        Integer refundType = 0;
        Integer refundFeeNew = 0;
        if (req.getRefundType() != null && req.getRefundType() != 0) {
            if (req.getRefundFee() == null || req.getRefundFee() <= 0) {
                throw new BusinessException("输入退款金额错误");
            }
            if (req.getRefundFee() >= orderInfo.getTotalFee()) {
                throw new BusinessException("部分退款金额不能大于等于总金额");
            }
            refundType = 1;
            refundFeeNew = req.getRefundFee();
        } else {
            refundFeeNew = orderInfo.getTotalFee();
        }
//        if (refundFee.intValue() > orderInfo.getTotalFee().intValue()) {
//            log.error(":>>> 订单:{} 退款金额:{} 不能大于用户支付金额:{}", req.getId(), req.getRefundFee(), orderInfo.getTotalFee());
//            throw new BusinessException("退款金额不能大于支付金额");
//        }
        for (String subId : req.getSubOrders().keySet()) {
            Query query1 = new Query();
            query1.addCriteria(Criteria.where("oOrderNo").is(subId));
            Update update = new Update();
            update.set("verifyStatus", 1);
            update.set("status", "9");
            update.set("refundFee", req.getSubOrders().get(subId));
            update.set("refundDesc", req.getRefundDesc());
            update.set("updatedTime", new Date());
            update.set("refundStatus", "2");
            update.set("refundApplyTime", new Date());
            UpdateResult updateResult = mongoTemplate.updateFirst(query1, update, OOrderInfo.class);
            log.info(":>>> 更新子订单:{} 的结果为:{}", subId, updateResult.getModifiedCount() > 0 ? true : false);
        }
        Update update = new Update();
        update.set("refundType", refundType);
        update.set("verifyStatus", 1);
        update.set("status", "9");
        update.set("refundFee", refundFeeNew);
        update.set("refundDesc", req.getRefundDesc());
        update.set("updatedTime", new Date());
//        退款状态,0:未退款,1:退款申请,2:退款中,3:退款完成,4:待返货,7:部分退款中
        update.set("refundStatus", "2");
        update.set("refundComment", req.getRefundComment());
        update.set("alipayAccount", req.getAlipayAccount());
        update.set("refundApplyTime", new Date());
        update.set("refundApplyUserType", req.getRefundApplyUserType());
        update.set("optName", req.getOptName());
        update.set("refundApplyPlatform", req.getRefundApplyPlatform());
        update.set("refundApplyAppId", req.getRefundApplyAppId());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, OrderInfo.class);
        log.info(":>>> 订单:{} 的退款预操作结果:{}", req.getId(), updateResult.getModifiedCount() > 0 ? true : false);
        return updateResult.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public void doOrderStatusJob(Integer hour) {
        Date time = DateUtils.addHours(new Date(), -hour);
        Query query = new Query();
        query.addCriteria(Criteria.where("status").is("1"));
        query.addCriteria(Criteria.where("payTime").lte(time));
        List<OrderInfo> list = this.mongoTemplate.find(query, OrderInfo.class);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list.stream().forEach(orderInfo -> {
            Query query1 = new Query();
            query1.addCriteria(Criteria.where("id").is(orderInfo.getId()));
            query1.addCriteria(Criteria.where("status").is("1"));
            Update update = new Update();
            update.set("status", "2");
            update.set("updatedTime", new Date());
            update.set("mark", "定时更新-定制中");
            this.mongoTemplate.updateMulti(query1, update, OrderInfo.class);
            Query querySubOrder = new Query().addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()));
            this.mongoTemplate.updateMulti(querySubOrder, update, OOrderInfo.class);

        });
        list.clear();
    }

    @Override
    public void setRefundAndModify(OrderInfo orderInfo) {
        if (Objects.isNull(orderInfo) || StringUtils.isBlank(orderInfo.getActivityId())) {
            log.error(":>>> 订单为空");
            return;
        }
        ActivityInfo activityInfo =
                mongoTemplate.findOne(new Query().addCriteria(Criteria.where("id").is(orderInfo.getActivityId())),
                        ActivityInfo.class);

        if (!"1".equals(orderInfo.getStatus())) {
            orderInfo.setCanModifyAddress(false);
            orderInfo.setCanRefund(false);
            //2021-08-27 17:59:28 之前下单不能退款
        } else if (Objects.nonNull(orderInfo.getPayTime()) && orderInfo.getPayTime().getTime() <= 1630056628000L) {
            orderInfo.setCanModifyAddress(false);
            orderInfo.setCanRefund(false);
        } else {
            orderInfo.setCanModifyAddress(activityInfo.getCanModifyAddress());
            orderInfo.setCanRefund(activityInfo.getCanRefund());

        }
    }

    @Override
    public HashMap<String, String> enableRefund(String orderNo) {
        log.info(":>>> 开启退款订单编号:{}", orderNo);
        if (StringUtils.isBlank(orderNo)) {
            log.error(":>>> 订单编号为空");
            throw new BusinessException("订单编号为空");
        }
        Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(orderInfo)) {
            log.error(":>>> 订单不存在:{}", orderNo);
            throw new BusinessException("订单不存在");
        }
        if (!"1".equals(orderInfo.getStatus())) {
            log.error(":>>> 订单状态错误:{},非付款中订单", orderNo);
            throw new BusinessException("订单不支持退款");
        }
        Update update = new Update();
        update.set("supportRefund", true);
        update.set("updatedTime", new Date());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, OrderInfo.class);
        boolean re = updateResult.getModifiedCount() > 0 ? true : false;
        log.info(":>>> 开启订单退款状态:{},结果为:{}", orderNo, re);
        if (re) {
            HashMap<String, String> datas = new HashMap<>();
            datas.put("desc", refundDesc);
            String reUrl = String.format(platformConfigService.getBizFrontDomain() + refundUrl,
                    orderInfo.getActivityId(), orderInfo.getId(), orderInfo.getAppId());
            datas.put("refundUrl", reUrl);
            log.info(":>>> 返回的退款链接:{}", JSON.toJSONString(datas));
            return datas;

        }
        log.error(":>>> 退款失败:{}", orderNo);
        throw new BusinessException("退款失败,请联系客服");
    }

    @Override
    public void orderAnalysis() {
        log.info(":>>> 开始订单分析");
        Query query = new Query();
        query.addCriteria(Criteria.where("status").ne("0"));
        List<OrderInfo> orderInfos = mongoTemplate.find(query, OrderInfo.class);
        log.info(":>>> 总的订单量:{}", orderInfos.size());
        HashMap<Long, Integer> payMap = new HashMap<>();
        payMap.put(65535L, orderInfos.size());
        int counter = 0;
        for (OrderInfo orderInfo : orderInfos) {
            log.info(":>>> 开始处理的数量:{}", counter);
            if (StringUtils.isNotBlank(orderInfo.getMobile())) {
                Query query1 =
                        new Query().addCriteria(Criteria.where("mobile").is(orderInfo.getMobile()).and("id").ne(orderInfo.getId()));
                Long count = mongoTemplate.count(query1, OrderInfo.class);
                Long p = count + 1;
                if (payMap.containsKey(p)) {
                    payMap.put(p, payMap.get(p) + 1);
                } else {
                    payMap.put(p, +1);
                }
            }
            counter++;
        }
        log.info(":>>> 购买统计:{}", JSON.toJSONString(payMap));

    }

    @Override
    public String exportExpressOrder(OrderRequest req, HttpServletResponse response) {
        log.info(":>>> 开始发货订单导出:{}", JSON.toJSONString(req));
        HashMap<String, UniversityInfo> universityInfoHashMap = new HashMap<>();
        Query query = (Query) this.getOrderQuery(req, false).get("query");
        Long count = mongoTemplate.count(query, OrderInfo.class);
        log.info(":>>> 订单导出总数量:{}", count);
        if (count.compareTo(0L) == -1) {
            log.error(":>>> 用户 订单为空");
            return "";
        }
        log.info(":>>> 订单总量:{}", count);
        FileExportTask fileExportTask = new FileExportTask();
        fileExportTask.setToken(req.getOptUserName());
        fileExportTask.setBizType("order");
        fileExportTask.setStatus(0);
        fileExportTask.setOptUser(req.getOptUserName());
        fileExportTask.setOptUserId(req.getUserId());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(new Date());
        ActivityInfo activityInfo = null;
        if (StringUtils.isNotBlank(req.getActivityId())) {
            Query queryA = new Query().addCriteria(Criteria.where("id").is(req.getActivityId()));
            activityInfo = mongoTemplate.findOne(queryA, ActivityInfo.class);
        }
        String fileName = "证书发货订单-" + System.currentTimeMillis();
        String f = fileName + System.currentTimeMillis() + ".xlsx";
        fileExportTask.setFileName(f);
        fileExportTask.setNum(count.intValue());
        fileExportTask.setDesc(activityInfo == null ? "证书发货订单" : activityInfo.getName() + "证书发货订单");
        String re = fileExportTaskService.create(fileExportTask);
        SystemOptLog optlog = new SystemOptLog();
        optlog.setIp(req.getIpAddress());
        optlog.setOptUserName(req.getOptUserName());
        optlog.setOptTime(new Date());
        optlog.setBizType("export-express-order");
        optlog.setOptRealName(req.getOptUserRealName());
        optlog.setSqlDetai(JSON.toJSONString(query, SerializerFeature.IgnoreNonFieldGetter));
        optlog.setDesc("导出证书订单供应链文件名:" + f + ",数据总条数:" + count);
        systemOptLogService.create(optlog);
        this.exportExpressOrder(query, count, f, re);
        return re;
    }

    @Override
    public String exportSingleOrder(OrderRequest req) {
        log.info(":>>> 开始合订单导出:{}", JSON.toJSONString(req));
        HashMap<String, UniversityInfo> universityInfoHashMap = new HashMap<>();
        Query query = new Query().addCriteria(Criteria.where("singleOrderBatchId").is(req.getBatchId()));
        Long count = mongoTemplate.count(query, OrderInfo.class);
        log.info(":>>> 订单导出总数量:{}", count);
        if (count.compareTo(0L) == -1) {
            log.error(":>>> 用户 订单为空");
            return "";
        }
        log.info(":>>> 订单总量:{}", count);
        FileExportTask fileExportTask = new FileExportTask();
        fileExportTask.setToken(req.getOptUserName());
        fileExportTask.setBizType("single-order");
        fileExportTask.setStatus(0);
        fileExportTask.setOptUser(req.getOptUserName());
        fileExportTask.setOptUserId(req.getUserId());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(new Date());
        ActivityInfo activityInfo = null;
        if (StringUtils.isNotBlank(req.getActivityId())) {
            Query queryA = new Query().addCriteria(Criteria.where("id").is(req.getActivityId()));
            activityInfo = mongoTemplate.findOne(queryA, ActivityInfo.class);
        }
        String fileName = "证书合单订单-" + (activityInfo == null ? "" : activityInfo.getName()) + "-" + dateStr;
        String f = fileName + System.currentTimeMillis() + ".xlsx";
        fileExportTask.setFileName(f);
        fileExportTask.setNum(count.intValue());
        fileExportTask.setDesc(activityInfo == null ? "证书合单订单" : activityInfo.getName() + "证书合单订单");
        String re = fileExportTaskService.create(fileExportTask);
        SystemOptLog optlog = new SystemOptLog();
        optlog.setIp(req.getIpAddress());
        optlog.setOptUserName(req.getOptUserName());
        optlog.setOptTime(new Date());
        optlog.setBizType("export-single-order");
        optlog.setOptRealName(req.getOptUserRealName());
        optlog.setSqlDetai(JSON.toJSONString(query, SerializerFeature.IgnoreNonFieldGetter));
        optlog.setDesc("导出证书订单合单文件名:" + f + ",数据总条数:" + count);
        systemOptLogService.create(optlog);
        this.exportSingleOrder(req.getBatchId(), query, count, f, re);
        return re;
    }

    @Override
    public boolean doRefund(OrderRefundOptVO req) {
        log.info(":>>> 开始退款审核操作:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || Objects.isNull(req.getVerifyStatus()) || StringUtils.isBlank(req.getId()) ||
                StringUtils.isBlank(req.getOptName()) || StringUtils.isBlank(req.getRefundWay()) ||
                StringUtils.isBlank(req.getRefundPayChannel())) {

            log.error(":>>> 退款审核操作参数错误");
            throw new BusinessException("退款审核操作参数错误");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(orderInfo)) {
            log.error(":>>> 证书订单不存在:{}", orderInfo.getId());
            throw new BusinessException("证书订单不存在");
        }
        //        退款状态,0:未退款,1:退款申请,2:退款中,3:退款完成,4:待返货 7:部分退款中
        if (!orderInfo.getRefundStatus().equals("2")) {
            log.error(":>>> 订单:{} 订单状态错误,不是退款中订单", req.getId());
            return false;
        }
        Query querySubOrder = new Query();
        querySubOrder.addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()));
//        querySubOrder.addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()).and("verifyStatus").is(1));
        List<OOrderInfo> subOrders = mongoTemplate.find(querySubOrder, OOrderInfo.class);
        if (CollectionUtils.isEmpty(subOrders)) {
            log.error(":>>> 订单:{} 退款子订单不存在", req.getId());
            throw new BusinessException("订单退款子订单不存在");
        }
//        0: 无需要审核,1:待审核,2:审核通过,3:审核拒绝
        switch (req.getVerifyStatus()) {
            // 审核通过
            case 2:
                return doRefundPassVerify(req, orderInfo, subOrders);
            // 审核拒绝
            case 3:
                return doRefunfRejectVerify(req, orderInfo);
            default:
                break;

        }
        return false;
    }

    @Override
    public boolean batchDoRefund(List<OrderRefundOptVO> reqs) {
        log.info(":>>> 开始处理批量退款:{}", JSON.toJSON(reqs));
        for (OrderRefundOptVO o : reqs) {
            this.doRefund(o);
        }

        return false;
    }

    @Override
    public OrderInfo findByOrderNo(String orderNo) {
        if (StringUtils.isBlank(orderNo)) {
            log.error(":>>> 订单编号为空");
            return null;
        }
        Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo));
        return mongoTemplate.findOne(query, OrderInfo.class);
    }

    @Override
    public boolean updateStatus() {
        log.info(":>>> 开始更新订单状态");
        List<String> status = new ArrayList<>();
        //0:待付款,1:已付款,2:制作中,3:待发货,4:待收货,5:已收货,6:订单完成,7:订单关闭,8:售后中,9:退款中,10:部分已发货
        status.add("1");
        status.add("2");
        status.add("3");
        Query query = new Query().addCriteria(Criteria.where("status").in(status));
        List<OrderInfo> orderInfos = mongoTemplate.find(query, OrderInfo.class);
        if (!CollectionUtils.isNotEmpty(orderInfos)) {
            return false;
        }
        log.info(":>>> 待处理订单数量:{}", orderInfos.size());
        int i = 0;
        for (OrderInfo orderInfo : orderInfos) {
            Query querySub = new Query().addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()));
            List<OOrderInfo> subs = mongoTemplate.find(querySub, OOrderInfo.class);
            if (CollectionUtils.isEmpty(subs)) {
                log.error(":>>> 主订单无子订单:{}", orderInfo.getOrderNo());
                continue;
            }
            List<String> logs = new ArrayList<>();
            for (OOrderInfo oOrderInfo : subs) {
                if (StringUtils.isNotBlank(oOrderInfo.getLogisticsNo())) {
                    logs.add(oOrderInfo.getLogisticsNo());
                }
                if (StringUtils.isNotBlank(oOrderInfo.getPostSaleLogisticsNo())) {
                    logs.add(oOrderInfo.getPostSaleLogisticsNo());
                }
            }
            if (!CollectionUtils.isEmpty(logs)) {
                Update update = new Update();
                update.set("status", "4");
                update.set("logisticsNos", logs);
                update.set("updatedTime", new Date());
                mongoTemplate.updateFirst(new Query().addCriteria(Criteria.where("id").is(orderInfo.getId())), update
                        , OrderInfo.class);

            }
            i++;
            log.info(":>>> 处理订单数量:{}", i);
        }
        return true;
    }

    @Override
    public List<MyOrderResponse> findByUserAndActivityId(UserPO currentUser, String activityId) {
        if (Objects.isNull(currentUser) || StringUtils.isBlank(activityId)) {
            return null;
        }
        String userId = currentUser.getId();
        String currentPlatform = currentUser.getCurrentPlatform();
        String appId = currentUser.getAppId();
        log.info("【获取用户订单】userId -> {}| currentPlatform ->{}| appId-> {}| activityId->{}", userId, currentPlatform,
                appId, activityId);
        Query query = new Query();
        query.addCriteria(Criteria.where("accountInfoId").is(userId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        query.addCriteria(Criteria.where("appId").is(appId));
        query.addCriteria(Criteria.where("platform").is(currentPlatform));
        query.addCriteria(Criteria.where("category").is("ca"));
        List<OrderInfo> orderInfoList = this.mongoTemplate.find(query, OrderInfo.class);
        if (CollectionUtils.isEmpty(orderInfoList)) {
            return null;
        }
        List<String> orderNoList = orderInfoList.stream().map(OrderInfo::getOrderNo).collect(Collectors.toList());
        //获取子订单-根据目前业务一个子订单目前只有一条
        query = new Query();
        query.addCriteria(Criteria.where("orderNo").in(orderNoList));
        List<OOrderInfo> subOrderInfoList = this.mongoTemplate.find(query, OOrderInfo.class);
        return subOrderInfoList.stream().map(oOrderInfo -> {
            MyOrderResponse myOrder = new MyOrderResponse();
            myOrder.setCaInfoId(oOrderInfo.getItemInfoId());
            myOrder.setOrderNo(oOrderInfo.getOrderNo());
            CaInfo caInfo = caInfoService.findOne(oOrderInfo.getItemInfoId());
            if (Objects.isNull(caInfo)) {
                return myOrder;
            }
            myOrder.setCaLevel(caInfo.getLevel());
            CaGroupInfo caGroupInfo = caGroupInfoService.findOne(caInfo.getCaGroupInfoId());
            if (Objects.nonNull(caGroupInfo)) {
                myOrder.setCaType(caGroupInfo.getTaskBizType());
            }
            return myOrder;
        }).collect(Collectors.toList());
    }

    @Override
    public String exportRefundOrder(OrderRequest req, HttpServletResponse response) {
        log.info(":>>> 开始导出退款订单:{}", JSON.toJSONString(req));
        if (Objects.isNull(req)) {
            return "";
        }
        if (StringUtils.isBlank(req.getActivityId())) {
            throw new BusinessException("活动ID不能为空");
        }
        HashMap<String, UniversityInfo> universityInfoHashMap = new HashMap<>();
        Query query = new Query();
        if (StringUtils.isNotBlank(req.getActivityId())) {
            query.addCriteria(Criteria.where("activityId").is(req.getActivityId()));
        }
        query.addCriteria(Criteria.where("refundStatus").is("3"));
        Long count = mongoTemplate.count(query, OrderInfo.class);
        log.info(":>>> 订单退款订单导出总数量:{}", count);
        if (count.compareTo(0L) == -1) {
            log.error(":>>> 用户 订单为空");
            return "";
        }
        log.info(":>>> 退款订单总量:{}", count);
        FileExportTask fileExportTask = new FileExportTask();
        fileExportTask.setToken(req.getOptUserName());
        fileExportTask.setBizType("refund-order");
        fileExportTask.setStatus(0);
        fileExportTask.setOptUser(req.getOptUserName());
        fileExportTask.setOptUserId(req.getUserId());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(new Date());
        ActivityInfo activityInfo = null;
        if (StringUtils.isNotBlank(req.getActivityId())) {
            Query queryA = new Query().addCriteria(Criteria.where("id").is(req.getActivityId()));
            activityInfo = mongoTemplate.findOne(queryA, ActivityInfo.class);
        }
        String fileName = "证书退款订单-" + (activityInfo == null ? "" : activityInfo.getName()) + "-" + dateStr;
        String f = fileName + System.currentTimeMillis() + ".xlsx";
        fileExportTask.setFileName(f);
        fileExportTask.setNum(count.intValue());
        fileExportTask.setDesc(activityInfo == null ? "证书退款订单" : activityInfo.getName() + "证书退款订单");
        String re = fileExportTaskService.create(fileExportTask);
        SystemOptLog optlog = new SystemOptLog();
        optlog.setIp(req.getIpAddress());
        optlog.setOptUserName(req.getOptUserName());
        optlog.setOptTime(new Date());
        optlog.setBizType("refund-order");
        optlog.setOptRealName(req.getOptUserRealName());
        optlog.setSqlDetai(JSON.toJSONString(query, SerializerFeature.IgnoreNonFieldGetter));
        optlog.setDesc("导出证书退款订单文件名:" + f + ",数据总条数:" + count);
        systemOptLogService.create(optlog);
        this.exportRefundOrder(req.getBatchId(), query, count, f, re);
        return re;
    }

    @Override
    public Boolean getBuyOrderByUserId(String userId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("accountInfoId").is(userId));
        query.addCriteria(Criteria.where("status").ne("0"));
        return this.mongoTemplate.exists(query, OrderInfo.class);
    }

    @Override
    public void doWechatMiniRefundOrder(String platform) {
        log.info(":>>> 开始处理小程序平台的退款申请:{}", platform);
        Query query = new Query();
        query.addCriteria(Criteria.where("refundApplyPlatform").is(platform));
        query.addCriteria(Criteria.where("refundStatus").is("2"));
        List<OrderInfo> list = this.mongoTemplate.find(query, OrderInfo.class);
        log.info(":>>> 小程序退款待审核的数量:{}", list == null ? 0 : list.size());
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list.stream().forEach(orderInfo -> {
            try {
                OrderRefundOptVO req = new OrderRefundOptVO();
                req.setId(orderInfo.getId());
                req.setVerifyStatus(2);
                req.setOptName("zhuhuaiqi");
                req.setRefundWay("on-line");
                req.setRefundPayChannel("微信");
                this.doRefund(req);
            } catch (Exception e) {
                log.error(":>>> 处理订单:{} 退款异常:{}", e);
            }

        });
        list.clear();
    }

    @Override
    public void doWechatH5RefundOrder(String platform) {
        log.info(":>>> 开始处理H5平台的退款申请:{}", platform);
        Query query = new Query();
        query.addCriteria(Criteria.where("refundApplyPlatform").ne(platform));
        query.addCriteria(Criteria.where("refundStatus").is("2"));
        List<OrderInfo> list = this.mongoTemplate.find(query, OrderInfo.class);
        log.info(":>>> H5平台退款待审核的数量:{}", list == null ? 0 : list.size());
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list.stream().forEach(orderInfo -> {
            try {
                OrderRefundOptVO req = new OrderRefundOptVO();
                req.setId(orderInfo.getId());
                req.setVerifyStatus(2);
                req.setOptName("zhuhuaiqi");
                req.setRefundWay("on-line");
                req.setRefundPayChannel("微信");
                this.doRefund(req);
            } catch (Exception e) {
                log.error(":>>> 处理订单:{} 退款异常:{}", e);
            }

        });
        list.clear();
    }

    @Override
    public List<OrderInfo> syncCaNumber(String batchId, Date start, Date end) {
        log.info(":>>> 开始同步证书编号:{},{},{}", batchId, start, end);
        Query query = new Query();
        Criteria criteriaPay = new Criteria();
        if (start != null || end != null) {
            criteriaPay = Criteria.where("payTime");
            if (start != null) {
                criteriaPay.gte(start);
            }
            if (end != null) {
                criteriaPay.lte(end);
            }
        }
        query.addCriteria(criteriaPay);
        query.addCriteria(Criteria.where("status").ne("0"));
        query.addCriteria(Criteria.where("delete").ne(Boolean.TRUE));
        List<OrderInfo> orderInfos = mongoTemplate.find(query, OrderInfo.class);
        return orderInfos;
    }

    @Override
    public void updateByMobileAndActivityId(String mobile, String toMobile, String activityId, String name, String universityId,
                                            String universityName, String userId) {
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(activityId)) {
            return;
        }
        Query query = new Query().addCriteria(Criteria.where("mobile").is(mobile).and("activityId").is(activityId));
        if (StringUtils.isNotBlank(userId)) {
            query.addCriteria(Criteria.where("accountInfoId").is(userId));
        }
        Update update = new Update();
        Date date = new Date();
        boolean toUpdate = false;
        if (StringUtils.isNotBlank(name)) {
            update.set("caPrintName", name);
            toUpdate = true;
        }
        if (StringUtils.isNotBlank(universityId)) {
            update.set("universityId", universityId);
            toUpdate = true;
        }
        if (StringUtils.isNotBlank(universityName)) {
            update.set("universityName", universityName);
            toUpdate = true;
        }
        if (StringUtils.isNotBlank(toMobile) && !mobile.equals(toMobile)) {
            update.set("mobile", toMobile);
            toUpdate = true;
        }
        if (toUpdate) {
            update.set("updatedTime", date);
            mongoTemplate.updateMulti(query, update, OrderInfo.class);
        }
    }


    public void setResponseHeader(HttpServletResponse response, String fileName) {
        try {
            fileName = new String(fileName.getBytes());
            response.reset();
            response.setContentType("application/msexcel");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Cache-Control", "no-cache");
        } catch (Exception ex) {
            log.error(":>>> setResponseHeader error:{}", ex);
        }
    }

    private void setCaOrderExcelTitle(SXSSFWorkbook workbook, SXSSFSheet sheet) {
        SXSSFRow row = sheet.createRow(0);
        //设置列宽，setColumnWidth的第二个参数要乘以256，这个参数的单位是1/256个字符宽度
        sheet.setColumnWidth(0, 10 * 256);
        sheet.setColumnWidth(1, 20 * 256);
        sheet.setColumnWidth(2, 20 * 256);
        sheet.setColumnWidth(3, 20 * 256);

        //设置为居中加粗

        SXSSFCell cell;
        cell = row.createCell(0);
        cell.setCellValue("证书名");
//        cell.setCellStyle(style);

        cell = row.createCell(1);
        cell.setCellValue("证书编号");
//        cell.setCellStyle(style);

        cell = row.createCell(2);
        cell.setCellValue("订单编号");
//        cell.setCellStyle(style);

        cell = row.createCell(3);
        cell.setCellValue("订单状态");
//        cell.setCellStyle(style);

        cell = row.createCell(4);
        cell.setCellValue("物流公司");
//        cell.setCellStyle(style);

        cell = row.createCell(5);
        cell.setCellValue("物流编号");
//        cell.setCellStyle(style);

        cell = row.createCell(6);
        cell.setCellValue("活动名称");
//        cell.setCellStyle(style);

        cell = row.createCell(7);
        cell.setCellValue("大学");
//        cell.setCellStyle(style);

        cell = row.createCell(8);
        cell.setCellValue("姓名");
//        cell.setCellStyle(style);

        cell = row.createCell(9);
        cell.setCellValue("电话");
//        cell.setCellStyle(style);

        cell = row.createCell(10);
        cell.setCellValue("支付时间");
//        cell.setCellStyle(style);

        cell = row.createCell(11);
        cell.setCellValue("证书材质");
//        cell.setCellStyle(style);
        cell = row.createCell(12);
        cell.setCellValue("省");
//        cell.setCellStyle(style);
        cell = row.createCell(13);
        cell.setCellValue("市");
//        cell.setCellStyle(style);
        cell = row.createCell(14);
        cell.setCellValue("区");
//        cell.setCellStyle(style);
        cell = row.createCell(15);
        cell.setCellValue("地址");
//        cell.setCellStyle(style);
        cell = row.createCell(16);
        cell.setCellValue("单价");
//        cell.setCellStyle(style);
        cell = row.createCell(17);
        cell.setCellValue("微信交易号");
//        cell.setCellStyle(style);
        cell = row.createCell(18);
        cell.setCellValue("退款金额");
//        cell.setCellStyle(style);
        cell = row.createCell(19);
        cell.setCellValue("退款时间");
//        cell.setCellStyle(style);
        cell = row.createCell(20);
        cell.setCellValue("订单备注");
//        cell.setCellStyle(style);
        cell = row.createCell(21);
        cell.setCellValue("订单标示");
//        cell.setCellStyle(style);
        cell = row.createCell(22);
        cell.setCellValue("平台");
//        cell.setCellStyle(style);
        cell = row.createCell(23);
        cell.setCellValue("大学");
//        cell.setCellStyle(style);
        cell = row.createCell(24);
        cell.setCellValue("礼品");
//        cell.setCellStyle(style);
        cell = row.createCell(25);
        cell.setCellValue("订单总价");
//        cell.setCellStyle(style);
        cell = row.createCell(26);
        cell.setCellValue("是否需要合单");
//        cell.setCellStyle(style);
        cell = row.createCell(27);
        cell.setCellValue("等级");
//        cell.setCellStyle(style);
        cell = row.createCell(28);
        cell.setCellValue("证书打印名字");
//        cell.setCellStyle(style);
        cell = row.createCell(29);
        cell.setCellValue("参与活动次数");
//        cell.setCellStyle(style);
        cell = row.createCell(30);
        cell.setCellValue("邀请人数");
//        cell.setCellStyle(style);
        cell = row.createCell(31);
        cell.setCellValue("学校城市");
//        cell.setCellStyle(style);
        cell = row.createCell(32);
        cell.setCellValue("学校类型");
//        cell.setCellStyle(style);
        cell = row.createCell(33);
        cell.setCellValue("学校人数");
//        cell.setCellStyle(style);
        cell = row.createCell(34);
        cell.setCellValue("学校等级");
//        cell.setCellStyle(style);
        cell = row.createCell(35);
        cell.setCellValue("是否合并");
//        cell.setCellStyle(style);
        cell = row.createCell(36);
        cell.setCellValue("就业率");
//        cell.setCellStyle(style);
        cell = row.createCell(37);
        cell.setCellValue("成立时间");
//        cell.setCellStyle(style);
        cell = row.createCell(38);
        cell.setCellValue("学校标签");
//        cell.setCellStyle(style);
        cell = row.createCell(39);
        cell.setCellValue("证书编号");
//        cell.setCellStyle(style);
        cell = row.createCell(40);
        cell.setCellValue("报名姓名");
//        cell.setCellStyle(style);
        cell = row.createCell(41);
        cell.setCellValue("报名手机号");
//        cell.setCellStyle(style);
        cell = row.createCell(42);
        cell.setCellValue("退款发起类型");
//        cell.setCellStyle(style);
        cell = row.createCell(43);
        cell.setCellValue("退款申请时间");
//        cell.setCellStyle(style);
        cell = row.createCell(44);
        cell.setCellValue("退款通过审核时间");
//        cell.setCellStyle(style);
        cell = row.createCell(45);
        cell.setCellValue("退款申请理由");
//        cell.setCellStyle(style);
        cell = row.createCell(46);
        cell.setCellValue("子订单号");
//        cell.setCellStyle(style);
        cell = row.createCell(47);
        cell.setCellValue("openId");
//        cell.setCellStyle(style);
        cell = row.createCell(48);
        cell.setCellValue("unionId");
//        cell.setCellStyle(style);
        cell = row.createCell(49);
        cell.setCellValue("是否是礼品");
//        cell.setCellStyle(style);
        cell = row.createCell(50);
        cell.setCellValue("商品图片");
//        cell.setCellStyle(style);
        cell = row.createCell(51);
        cell.setCellValue("运费");
        cell = row.createCell(52);
        cell.setCellValue("商品数量");
        cell = row.createCell(53);
        cell.setCellValue("子订单金额");
        cell = row.createCell(54);
        cell.setCellValue("商品ID");
        cell = row.createCell(55);
        cell.setCellValue("商品名");
    }

    private void setExpressOrderExcelTitle(XSSFWorkbook workbook, XSSFSheet sheet) {
        XSSFRow row = sheet.createRow(0);
        //设置列宽，setColumnWidth的第二个参数要乘以256，这个参数的单位是1/256个字符宽度
        sheet.setColumnWidth(0, 10 * 256);
        sheet.setColumnWidth(1, 20 * 256);
        sheet.setColumnWidth(2, 20 * 256);
        sheet.setColumnWidth(3, 20 * 256);

        //设置为居中加粗
        XSSFCellStyle style = workbook.createCellStyle();
        XSSFFont font = workbook.createFont();
        style.setFont(font);

        XSSFCell cell;
        cell = row.createCell(0);
        cell.setCellValue("礼品");
        cell.setCellStyle(style);

        cell = row.createCell(1);
        cell.setCellValue("证书材质");
        cell.setCellStyle(style);

        cell = row.createCell(2);
        cell.setCellValue("等级");
        cell.setCellStyle(style);

        cell = row.createCell(3);
        cell.setCellValue("大学");
        cell.setCellStyle(style);

        cell = row.createCell(4);
        cell.setCellValue("证书打印姓名");
        cell.setCellStyle(style);

        cell = row.createCell(5);
        cell.setCellValue("证书编号");
        cell.setCellStyle(style);


        cell = row.createCell(6);
        cell.setCellValue("姓名");
        cell.setCellStyle(style);

        cell = row.createCell(7);
        cell.setCellValue("电话");
        cell.setCellStyle(style);

        cell = row.createCell(8);
        cell.setCellValue("省");
        cell.setCellStyle(style);

        cell = row.createCell(9);
        cell.setCellValue("市");
        cell.setCellStyle(style);
        cell = row.createCell(10);
        cell.setCellValue("区");
        cell.setCellStyle(style);
        cell = row.createCell(11);
        cell.setCellValue("地址");
        cell.setCellStyle(style);
        cell = row.createCell(12);
        cell.setCellValue("是否需要合单");
        cell.setCellStyle(style);
        cell = row.createCell(13);
        cell.setCellValue("订单编号");
        cell.setCellStyle(style);
        cell = row.createCell(14);
        cell.setCellValue("子订单编号");
        cell.setCellStyle(style);
        cell = row.createCell(15);
        cell.setCellValue("微信交易号");
        cell.setCellStyle(style);
        cell = row.createCell(16);
        cell.setCellValue("订单标识");
        cell.setCellStyle(style);
        cell = row.createCell(17);
        cell.setCellValue("平台");
        cell.setCellStyle(style);
        cell = row.createCell(18);
        cell.setCellValue("OpenId");
        cell.setCellStyle(style);
        cell = row.createCell(19);
        cell.setCellValue("UnionId");
        cell.setCellStyle(style);
        cell = row.createCell(20);
        cell.setCellValue("活动名称");
        cell.setCellStyle(style);
        cell = row.createCell(21);
        cell.setCellValue("是否有礼品");
        cell.setCellStyle(style);
        cell = row.createCell(22);
        cell.setCellValue("订单状态");
        cell.setCellStyle(style);
        cell = row.createCell(23);
        cell.setCellValue("物流公司");
        cell.setCellStyle(style);
        cell = row.createCell(24);
        cell.setCellValue("物流编号");
        cell.setCellStyle(style);
        cell = row.createCell(25);
        cell.setCellValue("礼品配置是否出错");
        cell.setCellStyle(style);
        cell = row.createCell(26);
        cell.setCellValue("礼品原始配置");
        cell.setCellStyle(style);
        cell = row.createCell(27);
        cell.setCellValue("是否超买");
        cell.setCellStyle(style);
        cell = row.createCell(28);
        cell.setCellValue("定制周期");
        cell.setCellStyle(style);
        cell = row.createCell(29);
        cell.setCellValue("合单ID");
        cell.setCellStyle(style);
        cell = row.createCell(30);
        cell.setCellValue("合单批次号");
        cell.setCellStyle(style);
        cell = row.createCell(31);
        cell.setCellValue("商品数量");
        cell.setCellStyle(style);
        cell = row.createCell(32);
        cell.setCellValue("下单时等级");
        cell.setCellStyle(style);
        cell = row.createCell(33);
        cell.setCellValue("下单时证书名字");
        cell.setCellStyle(style);
        cell = row.createCell(35);
        cell.setCellValue("商户号ID");
        cell.setCellStyle(style);
        cell = row.createCell(36);
        cell.setCellValue("商户号");
        cell.setCellStyle(style);
        cell = row.createCell(37);
        cell.setCellValue("总费用（取值主订单，累计时注意订单号去重）");
        cell.setCellStyle(style);
        cell = row.createCell(38);
        cell.setCellValue("退款费用（取值主订单，累计时注意订单号去重）,注意订单状态");
        cell.setCellStyle(style);
        cell = row.createCell(39);
        cell.setCellValue("商品单价");
        cell.setCellStyle(style);
        cell = row.createCell(40);
        cell.setCellValue("商品名");
        cell.setCellStyle(style);
        cell = row.createCell(41);
        cell.setCellValue("领取电子证书日期");
        cell.setCellStyle(style);
        cell = row.createCell(42);
        cell.setCellValue("支付时间");
        cell.setCellStyle(style);
        cell = row.createCell(43);
        cell.setCellValue("退款类型");
        cell.setCellStyle(style);
        cell = row.createCell(44);
        cell.setCellValue("退款说明");
        cell.setCellStyle(style);
        cell = row.createCell(45);
        cell.setCellValue("总限时扣减");
        cell.setCellStyle(style);
        cell = row.createCell(46);
        cell.setCellValue("限时扣减");
        cell.setCellStyle(style);
        cell = row.createCell(47);
        cell.setCellValue("版本");
        cell.setCellStyle(style);
        cell = row.createCell(48);
        cell.setCellValue("商品数量");
        cell.setCellStyle(style);
        cell = row.createCell(49);
        cell.setCellValue("子订单金额");
        cell.setCellStyle(style);
        cell = row.createCell(50);
        cell.setCellValue("商品ID");
        cell.setCellStyle(style);
        cell = row.createCell(51);
        cell.setCellValue("商品名");
        cell.setCellStyle(style);
        cell = row.createCell(52);
        cell.setCellValue("是否组合商品");
        cell.setCellStyle(style);
        cell = row.createCell(53);
        cell.setCellValue("套装子商品1-名字");
        cell.setCellStyle(style);
        cell = row.createCell(54);
        cell.setCellValue("套装子商品1-ID");
        cell.setCellStyle(style);
        cell = row.createCell(55);
        cell.setCellValue("套装子商品2-名字");
        cell.setCellStyle(style);
        cell = row.createCell(56);
        cell.setCellValue("套装子商品2-ID");
        cell.setCellStyle(style);
        cell = row.createCell(57);
        cell.setCellValue("套装子商品3-名字");
        cell.setCellStyle(style);
        cell = row.createCell(58);
        cell.setCellValue("套装子商品3-ID");
        cell.setCellStyle(style);
        cell = row.createCell(59);
        cell.setCellValue("套装子商品4-名字");
        cell.setCellStyle(style);
        cell = row.createCell(60);
        cell.setCellValue("套装子商品4-ID");
        cell.setCellStyle(style);
        cell = row.createCell(61);
        cell.setCellValue("套装子商品5-名字");
        cell.setCellStyle(style);
        cell = row.createCell(62);
        cell.setCellValue("套装子商品5-ID");
        cell.setCellStyle(style);
        cell = row.createCell(63);
        cell.setCellValue("套装子商品6-名字");
        cell.setCellStyle(style);
        cell = row.createCell(64);
        cell.setCellValue("套装子商品6-ID");
        cell.setCellStyle(style);
        cell = row.createCell(65);
        cell.setCellValue("版本");
        cell.setCellStyle(style);
    }

    private void setRefundOrderExcelTitle(XSSFWorkbook workbook, XSSFSheet sheet) {
        XSSFRow row = sheet.createRow(0);
        //设置列宽，setColumnWidth的第二个参数要乘以256，这个参数的单位是1/256个字符宽度
        sheet.setColumnWidth(0, 10 * 256);
        sheet.setColumnWidth(1, 20 * 256);
        sheet.setColumnWidth(2, 20 * 256);
        sheet.setColumnWidth(3, 20 * 256);

        //设置为居中加粗
        XSSFCellStyle style = workbook.createCellStyle();
        XSSFFont font = workbook.createFont();
        style.setFont(font);

        XSSFCell cell;
        cell = row.createCell(0);
        cell.setCellValue("退款时间");
        cell.setCellStyle(style);

        cell = row.createCell(1);
        cell.setCellValue("订单编号");
        cell.setCellStyle(style);

        cell = row.createCell(2);
        cell.setCellValue("活动名称");
        cell.setCellStyle(style);

        cell = row.createCell(3);
        cell.setCellValue("姓名");
        cell.setCellStyle(style);

        cell = row.createCell(4);
        cell.setCellValue("收货人手机号");
        cell.setCellStyle(style);

        cell = row.createCell(5);
        cell.setCellValue("是否发货");
        cell.setCellStyle(style);


        cell = row.createCell(6);
        cell.setCellValue("是否投诉");
        cell.setCellStyle(style);

        cell = row.createCell(7);
        cell.setCellValue("退款方式");
        cell.setCellStyle(style);

        cell = row.createCell(8);
        cell.setCellValue("退款金额");
        cell.setCellStyle(style);

        cell = row.createCell(9);
        cell.setCellValue("退款处理人");
        cell.setCellStyle(style);
        cell = row.createCell(10);
        cell.setCellValue("退款申请时间");
        cell.setCellStyle(style);
        cell = row.createCell(11);
        cell.setCellValue("退款备注");
        cell.setCellStyle(style);
        cell = row.createCell(12);
        cell.setCellValue("退款审批人");
        cell.setCellStyle(style);
        cell = row.createCell(13);
        cell.setCellValue("大学");
        cell.setCellStyle(style);
    }

    /**
     * 设置订单状态字符串
     *
     * @param caStatus
     * @return
     */
    private String getOrderStatusStr(String caStatus) {
        String status = " ";
        if (Objects.nonNull(caStatus)) {

            switch (caStatus) {
                case "0":
                    status = "待付款";
                    break;
                case "1":
                    status = "已付款";
                    break;
                case "2":
                    status = "制作中";
                    break;
                case "3":
                    status = "待发货";
                    break;
                case "4":
                    status = "待收货";
                    break;
                case "5":
                    status = "已收货";
                    break;
                case "6":
                    status = "订单完成";
                    break;
                case "7":
                    status = "订单关闭";
                    break;
                case "8":
                    status = "售后中";
                    break;
                case "9":
                    status = "退款中";
                    break;
                case "10":
                    status = "待返货";
                    break;
                case "11":
                    status = "返货中";
                    break;
                case "12":
                    status = "退款完成";
                    break;
                default:
                    break;
            }
        }
        return status;
    }

    @Autowired
    private WechatPayRefundServiceFacotry wechatPayRefundServiceFacotry;

    private RefundOrderResult refund(QQWxRefundRequest request, String platform) {
        log.info("refund 发起退款 {}", JSON.toJSONString(request));

        WechatMerchantConfig config = null;
        if (StringUtils.isBlank(request.getOrderMerchantId())) {
            log.info("refund 订单的商户号为空 orderNo:{},appId:{}", request.getOrderNo(), request.getAppId());
            WechatConfigInfo configInfo = wechatConfigInfoService.find(request.getAppId());
            config.setMerchantId(configInfo.getMerchantId());
            config.setDesc(configInfo.getDesc());
            config.setCc(configInfo.getCc());
        } else {
            log.info("refund 订单的商户号为不为空 orderNo:{},merchantId:{}", request.getOrderNo(), request.getOrderMerchantId());
            config = wechatMerchantConfigService.findByMerchantIdAndDecrypt(request.getOrderMerchantId());
        }
        if (Objects.isNull(config)) {
            throw new BusinessException("获取商户配置异常");
        }
        request.setMerchantId(config.getMerchantId());
        request.setKey(config.getDesc());

        RefundRecord refundRecord = new RefundRecord();
        BeanUtils.copyProperties(request, refundRecord);
        refundRecord.setCreatedTime(new Date());
        log.info("refund 保存退款记录 refundRecord:{}", JSON.toJSONString(refundRecord));
        mongoTemplate.save(refundRecord);

        WeChatPayRefundService refundService = wechatPayRefundServiceFacotry.get(config);
        RefundOrderResult refundOrderResult = refundService.applyRefund(request);

        //更新退款记录结果
        refundRecord.setResult(refundOrderResult);
        mongoTemplate.save(refundRecord);
        log.info("refund 更新退款记录 refundRecord:{}", JSON.toJSONString(refundRecord));
        return refundOrderResult;

    }

    /**
     * 获取微信小程序支付退单
     *
     * @return
     */
    public boolean wxMinirefund(GoodsOrderDTO order, WechatMerchantConfig merchant) {
        log.info("WechatMiniService,refund,request param:{}", order);
        Map<String, String> resultMap = null;
        String nonceStr = CommonUtils.getRandomStringByLength(32);
        WXPayConfig config = wechatPayService.getWxPayConfig(order.getAppId(), merchant, true);
        try {
            WXPay wxpay = new WXPay(config);
            Map<String, String> param = new HashMap<>(16);
            //退款单号
            param.put("appid", order.getAppId());
            //商户号
            param.put("mch_id", config.getMchID());
            //总金额
            param.put("total_fee", order.getPrice().toString());
            //退款金额
            param.put("refund_fee", order.getRefundPrice().toString());
            //随机字符串
            param.put("nonce_str", nonceStr);
            //退款单号
            param.put("out_refund_no", order.getRefundNo());
            //商户单号
            param.put("out_trade_no", order.getOrderNo());
            // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            String prestr = PayUtil.createLinkString(param);
            //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            String mysign = PayUtil.sign(prestr, config.getKey(), "utf-8").toUpperCase();
            param.put("sign", mysign);
            resultMap = wxpay.refund(param);
            log.info("WechatMiniService,refund,openId:{} orderNo:{} refund result:{}", order.getOpenId(),
                    order.getOrderNo(), JSON.toJSONString(resultMap));
            if (resultMap != null && resultMap.get("result_code") != null && resultMap.get("result_code").equals(
                    "SUCCESS")) {
                return true;
            }
        } catch (Exception e) {
            log.error("WechatMiniService,refund,openId:{} orderNo:{},refund error", order.getOpenId(),
                    order.getOrderNo(), e);
        }
        return false;
    }

    public static void main(String[] args) {

        System.out.println(random(5));
    }

    private static Integer random(int max) {
        return ThreadLocalRandom.current().nextInt(max);
    }

    private String buildRefundParamXml(QQWxRefundRequest request, String nonceStr, Map<String, Object> param) {
        StringBuffer bf = new StringBuffer();

        bf.append("<xml>");
        if ("qq".equals(request.getPlatform())) {
            bf = appendElement(bf, "appid", request.getWechatAppId(), param);
        } else {
            bf = appendElement(bf, "appid", request.getAppId(), param);
        }

        bf = appendElement(bf, "mch_id", request.getMerchantId(), param);

        bf = appendElement(bf, "nonce_str", nonceStr, param);

        bf = appendElement(bf, "out_trade_no", request.getOrderNo(), param);

        bf = appendElement(bf, "out_refund_no", request.getRefundNo(), param);

        bf = appendElement(bf, "refund_fee", request.getRefundFee(), param);

        bf = appendElement(bf, "total_fee", request.getTotalFee(), param);

        bf = appendElement(bf, "refund_desc", request.getDesc(), param);

        String prestr = PayUtil.createLink(param);

        //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
        String sign = PayUtil.sign(prestr, request.getKey(), "utf-8").toUpperCase();
        log.info(":>>> 生成的签名:{}", sign);
        bf = appendElement(bf, "sign", sign, param);

        bf.append("</xml>");

        return bf.toString();
    }

    private StringBuffer appendElement(StringBuffer bf, String elementKey, Object elementValue,
                                       Map<String, Object> param) {
        bf.append("<" + elementKey + "><![CDATA[");
        bf.append(elementValue);
        bf.append("]]></" + elementKey + ">");
        if (param != null) {
            param.put(elementKey, elementValue);
        }
        return bf;
    }

    /**
     * 生成退款订单编号
     */
    public String generateRefundOrderNo(String itemNo) {

        RedisAtomicLong entityIdCounter = new RedisAtomicLong(refundOrderNoPreKey,
                redisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();
        log.info(":>>> 自增的长度为:{}", increment);
        if ((null == increment || increment.longValue() == 0)) {
            //初始设置过期时间
            entityIdCounter.expire(orderNoExpireTime, TimeUnit.SECONDS);
        }
        // goodsCode对应证书编码
        String orderNo =
                TimeUtils.formatDate(new Date(), "yyyyMMddHHmmssSSS") + (long) (Math.random() * (1000)) + "-" + entityIdCounter;
        log.info(":>>> 生成的订单编号为:{},{}", itemNo, orderNo);
        return orderNo;
    }

    /**
     * 发送发货短信
     *
     * @param mobile
     * @param activityId
     * @param params
     */
        private void sendShipMsg(String mobile, String activityId, String[] params) {
        ActivityInfo activityInfo = activityService.findOne(activityId);
        if (Objects.isNull(activityInfo)) {
            log.error(":>>> 活动不存在");
            return;
//            throw new BusinessException("活动不存在");
        }
        SmsTemplate smsTemplate = smsTemplateService.findBySmsTemplate("", activityInfo.getSmsSign(), "ship");
        if (Objects.isNull(smsTemplate) || StringUtils.isBlank(smsTemplate.getSign()) || Objects.isNull(smsTemplate.getTempalteId())) {
            log.error(":>>> 短信模版配置错误:没有配置");
            return;
//            throw new BusinessException("短信模版配置错误");
        }
        smsUtil.sendSmsWithContent(activityInfo.getSmsSign(), mobile, smsTemplate.getTempalteId(), params);

    }

        private void sendRefundMsg(String mobile, String activityId, String[] params) {
        log.info(":>>> 开始发送退款短信:{},{},{}", mobile, activityId, JSON.toJSONString(params));
        try {
            ActivityInfo activityInfo = activityService.findOne(activityId);
            if (Objects.isNull(activityInfo)) {
                log.error(":>>> 活动不存在");
                throw new BusinessException("活动不存在");
            }
            SmsTemplate smsTemplate = smsTemplateService.findBySmsTemplate("", activityInfo.getSmsSign(), "done" +
                    "-refund");
            if (Objects.isNull(smsTemplate) || StringUtils.isBlank(smsTemplate.getSign()) || Objects.isNull(smsTemplate.getTempalteId())) {
                log.error(":>>> 短信模版配置错误:没有配置");
                throw new BusinessException("短信模版配置错误");
            }
            smsUtil.sendSmsWithContent(activityInfo.getSmsSign(), mobile, smsTemplate.getTempalteId(), params);

        } catch (Exception e) {
            log.error(":>>> 发送退款短信错误:{}", e);
            return;
        }


    }


        private void exportOrder(Query query, Long count, String f, String exportTaskId) {
        HashMap<String, UniversityInfo> universityInfoHashMap = new HashMap<>();
        HashMap<String, ActivityInfo> activityInfoHashMap = new HashMap<>();
        int counter = 0;
        final BigDecimal decimal = new BigDecimal(100);
        SXSSFWorkbook workbook = new SXSSFWorkbook();
        HashMap<String, CaInfo> caInfoHashMap = new HashMap<>();
        try {
            int rowNum = 1;
            int sheetNum = 1;
            //创建一个Excel表单,参数为sheet的名字
            SXSSFSheet sheet = workbook.createSheet("sheet" + "-" + sheetNum);
            setCaOrderExcelTitle(workbook, sheet);
            //创建表头
            SXSSFRow row = null;
            Integer pageSize = 1000;
            Integer pages = count.intValue() / pageSize + 1;
            for (int page = 0; page < pages; page++) {
                log.info(":>>> 开始处理第:{} 页", page);
                if (page % 100 == 0) {
                    System.gc();
                    log.info(":>>>> 每10页执行Full GC :<<<<");
                }
                query.limit(pageSize);
                query.skip(page * pageSize);
                List<OrderInfo> contents = mongoTemplate.find(query, OrderInfo.class);
                if (Objects.isNull(contents) && CollectionUtils.isEmpty(contents)) {
                    log.error(":>>> 第:{} 页，数据为空", page);
                    continue;
                }
                String address = "";
                for (OrderInfo content : contents) {
                    Query subOrderQuery = new Query().addCriteria(Criteria.where("orderNo").is(content.getOrderNo()));
                    List<OOrderInfo> subOrders = mongoTemplate.find(subOrderQuery, OOrderInfo.class);
                    log.info(":>>> 开始处理订单:{},子订单数量:{}", content.getOrderNo(), subOrders.size());
                    if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(subOrders)) {
                        for (OOrderInfo oOrderInfo : subOrders) {
                            CaInfo caInfo = null;
                            if (StringUtils.isNotBlank(oOrderInfo.getItemInfoId())) {
                                if (caInfoHashMap.containsKey(oOrderInfo.getItemInfoId())) {
                                    caInfo = caInfoHashMap.get(oOrderInfo.getItemInfoId());
                                } else {
                                    caInfo = caInfoService.findOne(oOrderInfo.getItemInfoId());
                                    caInfoHashMap.put(oOrderInfo.getItemInfoId(), caInfo);
                                }

                            }
                            log.info(":>>> 导出行数:{}", counter);
                            if (counter != 0 && counter % 990000 == 0) {
                                //超过990000就自动创建一个sheet
                                sheetNum++;
                                sheet = workbook.createSheet("sheet-" + sheetNum);
                                setCaOrderExcelTitle(workbook, sheet);
                                //创建表头
                                //新增数据行，并且设置单元格数据
                                rowNum = 1;
                                sheetNum++;
                                log.info(":>>> 操作600000行,创建新sheet");
                            }
                            row = sheet.createRow(rowNum);
                            if (Objects.nonNull(oOrderInfo) && StringUtils.isNotBlank(oOrderInfo.getItemTitle())) {
                                String[] splitAddress = oOrderInfo.getItemTitle().split("，");

                                if (splitAddress.length == 3) {
                                    row.createCell(0).setCellValue(splitAddress[0]);
                                    row.createCell(11).setCellValue(splitAddress[2]);
                                    row.createCell(27).setCellValue(splitAddress[1]);

                                } else if (splitAddress.length == 2) {
                                    row.createCell(0).setCellValue(splitAddress[0]);
                                    row.createCell(11).setCellValue(splitAddress[1]);
                                }

                            }
                            if (Objects.nonNull(oOrderInfo.getTotalFee())) {
                                BigDecimal totalFee = new BigDecimal(oOrderInfo.getTotalFee());
                                row.createCell(53).setCellValue(totalFee.divide(decimal, 2, BigDecimal.ROUND_HALF_UP).toString());
                            } else {
                                BigDecimal salePrice = new BigDecimal(oOrderInfo.getSalePrice());
                                row.createCell(53).setCellValue(salePrice.divide(decimal, 2, BigDecimal.ROUND_HALF_UP).toString());
                            }
                            row.createCell(52).setCellValue(oOrderInfo.getNum());
                            // 订单编号
                            if (StringUtils.isNotBlank(content.getOrderNo())) {
                                row.createCell(2).setCellValue(content.getOrderNo());
                            }
                            // 订单状态
                            String caStatusStr = this.getOrderStatusStr(content.getStatus());
                            log.info(":>>> 订单状态:{}", caStatusStr);
                            row.createCell(3).setCellValue(caStatusStr);
                            if (StringUtils.isNotBlank(content.getLogisticsCompany())) {
                                row.createCell(4).setCellValue(content.getLogisticsCompany());
                            }
                            if (StringUtils.isNotBlank(content.getLogisticsNo())) {
                                row.createCell(5).setCellValue(content.getLogisticsNo());
                            }
                            if (StringUtils.isNotBlank(content.getActivityId())) {
                                ActivityInfo activityInfo = null;
                                if (activityInfoHashMap.containsKey(content.getActivityId())) {
                                    activityInfo = activityInfoHashMap.get(content.getActivityId());
                                } else {
                                    Query queryA =
                                            new Query().addCriteria(Criteria.where("id").is(content.getActivityId()));
                                    activityInfo = mongoTemplate.findOne(queryA, ActivityInfo.class);
                                    if (Objects.nonNull(activityInfo)) {
                                        activityInfoHashMap.put(content.getActivityId(), activityInfo);
                                    }
                                }

                                if (Objects.nonNull(activityInfo) && StringUtils.isNotBlank(activityInfo.getName())) {
                                    row.createCell(6).setCellValue(activityInfo.getName());
                                }
                            }
                            if (StringUtils.isNotBlank(content.getUniversityName())) {
                                row.createCell(7).setCellValue(content.getUniversityName());
                            }
                            if (StringUtils.isNotBlank(content.getName())) {
                                row.createCell(8).setCellValue(content.getName());
                            }
                            if (StringUtils.isNotBlank(content.getMobile())) {
                                row.createCell(9).setCellValue(content.getMobile());
                            }
                            if (Objects.nonNull(content.getPayTime())) {
                                String dateNowStr = TimeUtils.parse(content.getPayTime(), "yyyy-MM-dd HH:mm:ss");
                                row.createCell(10).setCellValue(dateNowStr);
                            }
                            if (StringUtils.isNotBlank(content.getProvince())) {
                                row.createCell(12).setCellValue(content.getProvince());
                            }
                            if (StringUtils.isNotBlank(content.getCity())) {
                                row.createCell(13).setCellValue(content.getCity());
                            }
                            if (StringUtils.isNotBlank(content.getArea())) {
                                row.createCell(14).setCellValue(content.getArea());
                            }
                            if (StringUtils.isNotBlank(content.getAddress())) {
                                address = filterAddress(content.getAddress(), content.getProvince(),
                                        content.getCity(), content.getArea(), content.getMobile());
                                if (StringUtils.isNotBlank(address)) {
                                    row.createCell(15).setCellValue(address);
                                }
                            }
                            if (Objects.nonNull(oOrderInfo.getSalePrice())) {
                                BigDecimal salePrice = new BigDecimal(oOrderInfo.getSalePrice());
                                row.createCell(16).setCellValue(salePrice.divide(decimal, 2,
                                        BigDecimal.ROUND_HALF_UP).toString());
                            }
                            if (Objects.nonNull(content.getTransactionId())) {
                                row.createCell(17).setCellValue(content.getTransactionId());
                            }
                            if (Objects.nonNull(content.getRefundFee())) {
                                row.createCell(18).setCellValue(content.getRefundFee());
                            }
//                        if (Objects.nonNull(content.getReceiveTime())) {
//                            String dateNowStr = TimeUtils.parse(content.getReceiveTime(), "yyyy-MM-dd HH:mm:ss");
//                            row.createCell(19).setCellValue(dateNowStr);
//                        }
                            if (StringUtils.isNotBlank(content.getTagsSearchStr())) {
                                row.createCell(20).setCellValue(content.getTagsSearchStr());
                            }
                            if (StringUtils.isNotBlank(content.getId())) {
                                row.createCell(21).setCellValue(content.getId());
                            }
                            if (StringUtils.isNotBlank(content.getPlatform())) {
                                row.createCell(22).setCellValue(content.getPlatform());
                            }
                            log.info(":>>> 大学ID:{}", content.getUniversityId());
                            if (StringUtils.isNotBlank(content.getUniversityId())) {
                                if (universityInfoHashMap.containsKey(content.getUniversityId())) {
                                    row.createCell(23).setCellValue(universityInfoHashMap.get(content.getUniversityId()).getName());
                                } else {
                                    Query query1 =
                                            new Query().addCriteria(Criteria.where("id").is(content.getUniversityId()));
                                    UniversityInfo universityInfo = mongoTemplate.findOne(query1, UniversityInfo.class);
                                    if (Objects.nonNull(universityInfo)) {
                                        row.createCell(23).setCellValue(universityInfo.getName());
                                        universityInfoHashMap.put(content.getUniversityId(), universityInfo);
                                    }
                                }
                            }
                            if (Objects.nonNull(oOrderInfo) && StringUtils.isNotBlank(oOrderInfo.getGift())) {
                                String g = oOrderInfo.getGift().replace("<P>", "");
                                g = g.replace("</p>", "");
                                row.createCell(24).setCellValue(g);
                            }
                            if (Objects.nonNull(content.getTotalFee())) {
                                BigDecimal totalFee = new BigDecimal(content.getTotalFee());
                                row.createCell(25).setCellValue(totalFee.divide(decimal, 2, BigDecimal.ROUND_HALF_UP).toString());
                            }
                            if (Objects.nonNull(content.getExtraExpressFee()) && content.getExtraExpressFee() > 0) {
                                BigDecimal extraExpressFee = new BigDecimal(content.getExtraExpressFee());
                                row.createCell(51).setCellValue(extraExpressFee.divide(decimal, 2,
                                        BigDecimal.ROUND_HALF_UP).toString());
                            }
                            if (subOrders.size() > 1) {
                                row.createCell(26).setCellValue("是");
                            } else {
                                row.createCell(26).setCellValue("否");
                            }
                            // 2021-05-28 00:36:07 之后版本更新了
                            if (Objects.nonNull(caInfo)) {
                                if (content.getCreatedTime().after(new Date(1622133367000L))) {
                                    if (StringUtils.isNotBlank(caInfo.getLevel())) {
                                        row.createCell(27).setCellValue(caInfo.getLevel());
                                    }
                                    if (StringUtils.isNotBlank(caInfo.getEdition())) {
                                        row.createCell(11).setCellValue(caInfo.getEdition());
                                    }
                                    if (StringUtils.isNotBlank(caInfo.getName())) {
                                        row.createCell(0).setCellValue(caInfo.getName());
                                    }
                                }

                            } else {
                                log.info(":>>> 证书信息为空:{},直接使用子订单中的证书名称", oOrderInfo.getItemInfoId());
                                if (StringUtils.isNotBlank(oOrderInfo.getItemTitle())) {
                                    row.createCell(0).setCellValue(oOrderInfo.getItemTitle());
                                }

                            }
                            if (Objects.nonNull(content.getCaPrintName())) {
                                row.createCell(28).setCellValue(content.getCaPrintName());
                            }
                            if (StringUtils.isNotBlank(content.getActivityId()) || StringUtils.isNotBlank(content.getAccountInfoId())) {
                                Query queryUp =
                                        new Query().addCriteria(Criteria.where("userId").is(content.getAccountInfoId()).and(
                                                "activityId").is(content.getActivityId()));
                                Long countUp = mongoTemplate.count(queryUp, UserParticipateActivityInfo.class);
                                if (Objects.nonNull(count)) {
                                    row.createCell(29).setCellValue(countUp.intValue());
                                }
                                Query queryInvite =
                                        new Query().addCriteria(Criteria.where("invitedByUserId").is(content.getAccountInfoId()).and("activityId").is(content.getActivityId()));
                                Long countInvite = mongoTemplate.count(queryInvite, UserInviteRecord.class);
                                if (Objects.nonNull(countInvite)) {
                                    row.createCell(30).setCellValue(countInvite.intValue());
                                }
                            }
                            if (StringUtils.isNotBlank(oOrderInfo.getCertificateNo())) {
                                row.createCell(39).setCellValue(oOrderInfo.getCertificateNo());
                            }
                            if (Objects.nonNull(content.getSignUpName())) {
                                row.createCell(40).setCellValue(content.getSignUpName());
                            }
                            if (Objects.nonNull(content.getSignUpMobile())) {
                                row.createCell(41).setCellValue(content.getSignUpMobile());
                            }
                            if (Objects.nonNull(content.getRefundApplyUserType())) {
//                            退款申请人类型platform:平台,visitor
                                switch (content.getRefundApplyUserType()) {
                                    case "visitor":
                                        row.createCell(42).setCellValue("用户发起");
                                        break;
                                    case "platform":
                                        row.createCell(42).setCellValue("平台发起");
                                        break;
                                }
                            }
                            if (Objects.nonNull(content.getRefundApplyTime())) {
                                String dateNowStr = TimeUtils.parse(content.getRefundApplyTime(), "yyyy-MM-dd " +
                                        "HH:mm:ss");
                                row.createCell(43).setCellValue(dateNowStr);
                            }
                            if ("3".equals(content.getRefundStatus())) {
                                Date date = content.getRefundTime();
                                if (Objects.isNull(date)) {
                                    date = content.getUpdatedTime();
                                }
                                if (Objects.nonNull(date)) {
                                    String dateNowStr = TimeUtils.parse(date, "yyyy-MM-dd HH:mm:ss");
                                    row.createCell(44).setCellValue(dateNowStr);
                                }
                            }
                            if (Objects.nonNull(content.getRefundComment())) {
                                row.createCell(45).setCellValue(content.getRefundComment());
                            }
                            if (Objects.nonNull(content.getRefundComment())) {
                                row.createCell(45).setCellValue(content.getRefundComment());
                            }
                            if (StringUtils.isNotBlank(oOrderInfo.getOOrderNo())) {
                                row.createCell(46).setCellValue(oOrderInfo.getOOrderNo());
                            }
                            if (StringUtils.isNotBlank(content.getOpenId())) {
                                row.createCell(47).setCellValue(content.getOpenId());
                                Query queryWechatUser =
                                        new Query().addCriteria(Criteria.where("openId").is(content.getOpenId()));
                                WechatH5UserPO wechatH5UserPO = mongoTemplate.findOne(queryWechatUser,
                                        WechatH5UserPO.class);
                                if (Objects.nonNull(wechatH5UserPO) && StringUtils.isNotBlank(wechatH5UserPO.getUnionId())) {
                                    row.createCell(48).setCellValue(wechatH5UserPO.getUnionId());
                                }
                            }
                            if (Objects.nonNull(caInfo)) {
                                if (Objects.nonNull(caInfo.getCaGift())) {
                                    if (Boolean.TRUE.equals(caInfo.getCaGift())) {
                                        row.createCell(49).setCellValue("是");
                                    } else {
                                        row.createCell(49).setCellValue("否");
                                    }
                                }
                            } else {
                                if (Objects.nonNull(oOrderInfo.getCaGift())) {
                                    if (Boolean.TRUE.equals(oOrderInfo.getCaGift())) {
                                        row.createCell(49).setCellValue("是");
                                    } else {
                                        row.createCell(49).setCellValue("否");
                                    }
                                }
                            }
                            if (StringUtils.isNotBlank(oOrderInfo.getItemImageUrl())) {
                                row.createCell(50).setCellValue(oOrderInfo.getItemImageUrl());
                            }
                            if (Objects.nonNull(caInfo)) {
                                row.createCell(54).setCellValue(caInfo.getId());
                                if (StringUtils.isNotBlank(caInfo.getName())) {
                                    row.createCell(55).setCellValue(caInfo.getName());
                                }
                            }
                            rowNum++;
                        }
                    }

                    counter++;
                }
            }

            //将excel写入到输出流中
            log.info(":>>> flush:{} 行", rowNum);
            OutputStream outputStream = new FileOutputStream(fileExportPath + f);
            workbook.write(outputStream);
            outputStream.flush();
            outputStream.close();
            log.info(":>>> 写文件到本地然后读:{}", f);
            File file = new File(fileExportPath + f);
            InputStream in = new FileInputStream(file);
            String url = fileService.uploadFile(in, f);
            Query queryTask = new Query().addCriteria(Criteria.where("id").is(exportTaskId));
            Update update = new Update();
            update.set("url", url);
            update.set("status", 1);
            update.set("updatedTime", new Date());
            UpdateResult updateResult = mongoTemplate.updateFirst(queryTask, update, FileExportTask.class);
            log.info(":>>> 更新任务:{},状态:{}", exportTaskId, updateResult.getModifiedCount() > 0 ? true : false);
            in.close();
            log.info(":>>> 订单内容导出,关闭文件流");
        } catch (Exception e) {
            log.error(":>>> 订单内容导出错误:{}", e);
        }
    }

    /**
     * 导出发货订单
     *
     * @param query
     * @param count
     * @param f
     * @param exportTaskId
     */
        private void exportExpressOrder(Query query, Long count, String f, String exportTaskId) {
        HashMap<String, UniversityInfo> universityInfoHashMap = new HashMap<>();
        HashMap<String, ActivityInfo> activityInfoHashMap = new HashMap<>();
        int counter = 0;
        XSSFWorkbook workbook = new XSSFWorkbook();
        HashMap<String, CaInfo> caInfoHashMap = new HashMap<>();
        try {
            int rowNum = 1;
            int sheetNum = 1;
            final BigDecimal decimal = new BigDecimal(100);
            //创建一个Excel表单,参数为sheet的名字
            XSSFSheet sheet = workbook.createSheet("sheet" + "-" + sheetNum);
            setExpressOrderExcelTitle(workbook, sheet);
            //创建表头
            XSSFRow row = null;
            Integer pageSize = 150000;
            Integer pages = count.intValue() / pageSize + 1;
            for (int page = 0; page < pages; page++) {
                log.info(":>>> 开始处理第:{} 页", page);
                if (page % 100 == 0) {
                    System.gc();
                    log.info(":>>>> 每{}页执行Full GC :<<<<", page);
                }
                query.limit(pageSize);
                query.skip(page * pageSize);
                List<OrderInfo> contents = mongoTemplate.find(query, OrderInfo.class);
                log.info(":>>>> 每{}页订单数量:{} :<<<<", page, contents == null ? 0 : contents.size());
                if (Objects.isNull(contents) && CollectionUtils.isEmpty(contents)) {
                    log.error(":>>> 第:{} 页，数据为空", page);
                    continue;
                }
                String address = "";
                for (OrderInfo content : contents) {
                    Query subOrderQuery = new Query().addCriteria(Criteria.where("orderNo").is(content.getOrderNo()));
                    List<OOrderInfo> subOrders = mongoTemplate.find(subOrderQuery, OOrderInfo.class);
                    log.info(":>>> 开始处理订单:{},子订单数量:{}", content.getOrderNo(), subOrders.size());
                    if (!CollectionUtils.isNotEmpty(subOrders)) {
                        log.error(":>>> 订单:{} 子订单为空", content.getOrderNo());
                        continue;
                    }
                    boolean isRefund = Lists.newArrayList("6", "9").contains(content.getStatus());
                    for (OOrderInfo oOrderInfo : subOrders) {
                        CaInfo caInfo = null;
                        if (StringUtils.isNotBlank(oOrderInfo.getItemInfoId())) {
                            if (caInfoHashMap.containsKey(oOrderInfo.getItemInfoId())) {
                                caInfo = caInfoHashMap.get(oOrderInfo.getItemInfoId());
                            } else {
                                log.info(":>>> 子订单:{},商品类目:{}", oOrderInfo.getOOrderNo(), content.getCategory());
                                switch (content.getCategory()) {
                                    case "ca":
                                        caInfo = caInfoService.findCaInfoById(oOrderInfo.getItemInfoId());
                                        if (Objects.nonNull(caInfo)) {
                                            caInfoHashMap.put(oOrderInfo.getItemInfoId(), caInfo);
                                        }
                                        break;
                                    case "gift":
                                        caInfo = caInfoService.findCaInfoById(oOrderInfo.getItemInfoId());
                                        if (Objects.nonNull(caInfo)) {
                                            caInfoHashMap.put(oOrderInfo.getItemInfoId(), caInfo);
                                        }
                                        break;
                                    case "item":
                                        ItemInfo itemInfo = itemInfoService.detail(oOrderInfo.getItemInfoId());
                                        if (Objects.nonNull(itemInfo)) {
                                            caInfo = new CaInfo();
                                            caInfo.setName(itemInfo.getTitle());
                                            caInfo.setId(oOrderInfo.getItemInfoId());
                                            caInfo.setPrice(itemInfo.getPrice());
                                            caInfo.setCategory(itemInfo.getCategory());
                                            caInfo.setCombinedCommodity(itemInfo.getCombinedCommodity());
                                            caInfoHashMap.put(oOrderInfo.getItemInfoId(), caInfo);
                                        }
                                        break;
                                    default:
                                        break;
                                }

                            }

                        }
                        log.info(":>>> 导出行数:{}", counter);
                        if (counter != 0 && counter % 990000 == 0) {
                            //超过990000就自动创建一个sheet
                            sheetNum++;
                            sheet = workbook.createSheet("sheet-" + sheetNum);
                            setExpressOrderExcelTitle(workbook, sheet);
                            //创建表头
                            //新增数据行，并且设置单元格数据
                            rowNum = 1;
                            sheetNum++;
                            log.info(":>>> 操作600000行,创建新sheet");
                        }
                        row = sheet.createRow(rowNum);
                        boolean gift = false;
                        // 礼品 第一列
                        if (Objects.nonNull(caInfo)) {

                            if (CollectionUtils.isNotEmpty(caInfo.getGiftItems()) || StringUtils.isNotBlank(caInfo.getGiftMaterialConfigId())) {
                                if (CollectionUtils.isNotEmpty(caInfo.getGiftItems())) {
                                    String g = "";
                                    for (GiftCaInfo c : caInfo.getGiftItems()) {
                                        if (StringUtils.isNotBlank(g)) {
                                            g = c.getName();
                                        } else {
                                            g = g + "+" + c.getName();
                                        }
                                    }
                                    if (StringUtils.isNotBlank(g)) {
                                        row.createCell(0).setCellValue(g);
                                        gift = true;
                                        row.createCell(25).setCellValue("否");
                                    }

                                } else if (StringUtils.isNotBlank(caInfo.getGiftMaterialConfigId())) {
                                    CaInfo caInfoGift =
                                            caInfoService.findCaInfoById(caInfo.getGiftMaterialConfigId());
                                    if (Objects.nonNull(caInfoGift) && StringUtils.isNotBlank(caInfoGift.getName())) {
                                        row.createCell(0).setCellValue(caInfoGift.getName());
                                        gift = true;
                                        row.createCell(25).setCellValue("否");
                                    } else {
                                        row.createCell(25).setCellValue("是");
                                    }
                                }

                            }

                        }
                        if (!gift) {
                            // 礼品 第一列
                            if (Objects.nonNull(oOrderInfo) && StringUtils.isNotBlank(oOrderInfo.getGift())) {
                                String g = oOrderInfo.getGift().replace("<P>", "");
                                g = g.replace("</p>", "");
                                g = g.replace("<p>", "");
                                row.createCell(0).setCellValue(g);
                                row.createCell(26).setCellValue(g);
                            }
                        }

                        // 证书材质 第2列
                        // 2021-05-28 00:36:07 之后版本更新了
                        log.info(":>>> 子订单:{} 证书信息为:{}", oOrderInfo.getOOrderNo(), caInfo == null ? null :
                                caInfo.getName());
                        if (Objects.nonNull(caInfo)) {

                            if (content.getCreatedTime().after(new Date(1622133367000L))) {
                                if (CollectionUtils.isNotEmpty(caInfo.getItemMaterialList())) {
                                    List<CaMaterialConfig> caMaterialIdList =
                                            caMaterialConfigService.findByCaMaterialIdList(caInfo.getItemMaterialList());
                                    if (CollectionUtils.isNotEmpty(caMaterialIdList)) {
                                        String caMaterial = caMaterialIdList.stream().map(CaMaterialConfig::getName).collect(Collectors.joining(","));
                                        if (Objects.nonNull(oOrderInfo.getCaItemType()) && 2 == oOrderInfo.getCaItemType()) {
                                            row.createCell(1).setCellValue(caMaterial + "*" + oOrderInfo.getNum());
                                        } else {
                                            row.createCell(1).setCellValue(caMaterial);
                                        }
                                    }
                                } else {
                                    CaMaterialConfig config = null;
                                    if (StringUtils.isNotBlank(caInfo.getMaterialConfigId())) {
                                        config = caMaterialConfigService.findOne(caInfo.getMaterialConfigId());
                                    }
                                    log.info(":>>> 子订单:{} 证书信息为:{},材质:{}", oOrderInfo.getOOrderNo(), caInfo == null ?
                                            null : caInfo.getName(), config == null ? null : config.getName());
                                    if (Objects.nonNull(config) && StringUtils.isNotBlank(config.getName())) {
                                        row.createCell(1).setCellValue(config.getName());
                                    } else {
                                        if (StringUtils.isNotBlank(caInfo.getEdition())) {
                                            row.createCell(1).setCellValue(caInfo.getEdition());
                                        }
                                    }
                                }

                                if (StringUtils.isNotBlank(caInfo.getLevel())) {
                                    row.createCell(2).setCellValue(caInfo.getLevel());
                                }
                                if (StringUtils.isNotBlank(caInfo.getEdition())) {
                                    row.createCell(47).setCellValue(caInfo.getEdition());
                                }

                            }
                            row.createCell(50).setCellValue(caInfo.getId());
                            row.createCell(51).setCellValue(caInfo.getName());
                        } else {
                            log.info(":>>> 子订单:{} 商品信息为空", oOrderInfo.getOOrderNo());
                            if (Objects.nonNull(oOrderInfo) && StringUtils.isNotBlank(oOrderInfo.getItemTitle())) {
                                String[] splitAddress = oOrderInfo.getItemTitle().split("，");

                                if (splitAddress.length == 3) {
                                    row.createCell(1).setCellValue(splitAddress[2]);
                                    row.createCell(2).setCellValue(splitAddress[1]);
                                } else if (splitAddress.length == 2) {
                                    row.createCell(1).setCellValue(splitAddress[1]);
                                }

                            }
                        }
                        log.info(":>>> 大学ID:{}", content.getUniversityId());
                        if (StringUtils.isNotBlank(content.getUniversityId())) {
                            if (universityInfoHashMap.containsKey(content.getUniversityId())) {
                                row.createCell(3).setCellValue(universityInfoHashMap.get(content.getUniversityId()).getName());
                            } else {
                                Query query1 =
                                        new Query().addCriteria(Criteria.where("id").is(content.getUniversityId()));
                                UniversityInfo universityInfo = mongoTemplate.findOne(query1, UniversityInfo.class);
                                if (Objects.nonNull(universityInfo)) {
                                    row.createCell(3).setCellValue(universityInfo.getName());
                                    universityInfoHashMap.put(content.getUniversityId(), universityInfo);
                                }
                            }
                        }
                        // 证书打印名字 第5列
                        if (Objects.nonNull(content.getCaPrintName())) {
                            row.createCell(4).setCellValue(content.getCaPrintName());
                        }
                        // 证书编号 第6列
                        if (StringUtils.isNotBlank(oOrderInfo.getCertificateNo())) {
                            row.createCell(5).setCellValue(oOrderInfo.getCertificateNo());
                        }
                        // 姓名 第7列
                        if (StringUtils.isNotBlank(content.getName())) {
                            row.createCell(6).setCellValue(content.getName());
                        }
                        // 电话 第8列
                        if (StringUtils.isNotBlank(content.getMobile())) {
                            row.createCell(7).setCellValue(content.getMobile());
                        }
                        // 省 第9列
                        if (StringUtils.isNotBlank(content.getProvince())) {
                            row.createCell(8).setCellValue(content.getProvince());
                        }
                        // 市 第10列
                        if (StringUtils.isNotBlank(content.getCity())) {
                            row.createCell(9).setCellValue(content.getCity());
                        }
                        // 区 第11列
                        if (StringUtils.isNotBlank(content.getArea())) {
                            row.createCell(10).setCellValue(content.getArea());
                        }
                        // 地址 第12列
                        if (StringUtils.isNotBlank(content.getAddress())) {
                            address = filterAddress(content.getAddress(), content.getProvince(),
                                    content.getCity(), content.getArea(), content.getMobile());
                            if (StringUtils.isNotBlank(address)) {
                                row.createCell(11).setCellValue(address);
                            }
                        }
                        // 是否需要合单 第13列
                        if (subOrders.size() > 1) {
                            row.createCell(12).setCellValue("是");
                        } else {
                            row.createCell(12).setCellValue("否");
                        }
                        // 订单编号 第14列
                        if (StringUtils.isNotBlank(content.getOrderNo())) {
                            row.createCell(13).setCellValue(content.getOrderNo());
                        }
                        // 子订单编号 第14列
                        if (StringUtils.isNotBlank(oOrderInfo.getOOrderNo())) {
                            row.createCell(14).setCellValue(oOrderInfo.getOOrderNo());
                        }
                        // 微信交易号 第16列
                        if (Objects.nonNull(content.getTransactionId())) {
                            row.createCell(15).setCellValue(content.getTransactionId());
                        }
                        // 订单标识 第17列
                        if (StringUtils.isNotBlank(content.getId())) {
                            row.createCell(16).setCellValue(content.getId());
                        }
                        // 平台 第18列
                        if (StringUtils.isNotBlank(content.getPlatform())) {
                            row.createCell(17).setCellValue(content.getPlatform());
                        }
                        if (StringUtils.isNotBlank(content.getOpenId())) {
                            row.createCell(18).setCellValue(content.getOpenId());
                            Query queryWechatUser =
                                    new Query().addCriteria(Criteria.where("openId").is(content.getOpenId()));
                            WechatH5UserPO wechatH5UserPO = mongoTemplate.findOne(queryWechatUser,
                                    WechatH5UserPO.class);
                            if (Objects.nonNull(wechatH5UserPO) && StringUtils.isNotBlank(wechatH5UserPO.getUnionId())) {
                                row.createCell(19).setCellValue(wechatH5UserPO.getUnionId());
                            }
                        }
                        if (StringUtils.isNotBlank(content.getActivityId())) {
                            ActivityInfo activityInfo = null;
                            if (activityInfoHashMap.containsKey(content.getActivityId())) {
                                activityInfo = activityInfoHashMap.get(content.getActivityId());
                            } else {
                                Query queryA =
                                        new Query().addCriteria(Criteria.where("id").is(content.getActivityId()));
                                activityInfo = mongoTemplate.findOne(queryA, ActivityInfo.class);
                                if (Objects.nonNull(activityInfo)) {
                                    activityInfoHashMap.put(content.getActivityId(), activityInfo);
                                }
                            }

                            if (Objects.nonNull(activityInfo) && StringUtils.isNotBlank(activityInfo.getName())) {
                                row.createCell(20).setCellValue(activityInfo.getName());
                            }
                        }
                        row.createCell(48).setCellValue(oOrderInfo.getNum());
                        if (Objects.nonNull(oOrderInfo.getTotalFee())) {
                            BigDecimal totalFee = new BigDecimal(oOrderInfo.getTotalFee());
                            row.createCell(49).setCellValue(totalFee.divide(decimal, 2, BigDecimal.ROUND_HALF_UP).toString());
                        } else {
                            BigDecimal salePrice = new BigDecimal(oOrderInfo.getSalePrice());
                            row.createCell(49).setCellValue(salePrice.divide(decimal, 2, BigDecimal.ROUND_HALF_UP).toString());
                        }
                        // 是否有礼品 第21列
                        if (Objects.nonNull(oOrderInfo.getCaGift())) {
                            if (Boolean.TRUE.equals(oOrderInfo.getCaGift())) {
                                row.createCell(21).setCellValue("是");
                            } else {
                                row.createCell(21).setCellValue("否");
                            }
                        }
                        // 订单状态
                        String caStatusStr = this.getOrderStatusStr(content.getStatus());
                        log.info(":>>> 订单状态:{}", caStatusStr);
                        row.createCell(22).setCellValue(caStatusStr);
                        if (StringUtils.isNotBlank(oOrderInfo.getLogisticsCompany())) {
                            row.createCell(23).setCellValue(oOrderInfo.getLogisticsCompany());
                        }
                        if (StringUtils.isNotBlank(oOrderInfo.getLogisticsNo())) {
                            row.createCell(24).setCellValue(oOrderInfo.getLogisticsNo());
                        }
                        if (Objects.nonNull(oOrderInfo.getOverbought())) {
                            row.createCell(27).setCellValue(oOrderInfo.getOverbought());
                        }
                        if (Objects.nonNull(oOrderInfo.getCaInfo())) {
                            row.createCell(32).setCellValue(oOrderInfo.getCaInfo().getLevel());
                            row.createCell(33).setCellValue(oOrderInfo.getCaInfo().getName());
                        }
                        if (Objects.nonNull(oOrderInfo.getNum())) {
                            row.createCell(31).setCellValue(oOrderInfo.getNum());
                        }
                        if (StringUtils.isNotBlank(content.getMechantId())) {
                            row.createCell(35).setCellValue(content.getMechantId());
                        }
                        if (StringUtils.isNotBlank(content.getMechantName())) {
                            row.createCell(36).setCellValue(content.getMechantName());
                        }
                        if (Objects.nonNull(content.getTotalFee())) {
                            BigDecimal totalFee = new BigDecimal(content.getTotalFee());
                            row.createCell(37).setCellValue(totalFee.divide(decimal, 2, BigDecimal.ROUND_HALF_UP).toString());
                        }
                        if (isRefund && Objects.nonNull(content.getRefundFee())) {
                            BigDecimal refundFee = new BigDecimal(content.getRefundFee());
                            row.createCell(38).setCellValue(refundFee.divide(decimal, 2, BigDecimal.ROUND_HALF_UP).toString());
                        }
                        if (Objects.nonNull(oOrderInfo.getSalePrice())) {
                            BigDecimal itemPrice = new BigDecimal(oOrderInfo.getSalePrice());
                            row.createCell(39).setCellValue(itemPrice.divide(decimal, 2, BigDecimal.ROUND_HALF_UP).toString());
                        } else if (Objects.nonNull(oOrderInfo.getSalePrice())) {
                            BigDecimal salePrice = new BigDecimal(oOrderInfo.getSalePrice());
                            row.createCell(39).setCellValue(salePrice.divide(decimal, 2, BigDecimal.ROUND_HALF_UP).toString());
                        }
                        if (StringUtils.isNotBlank(oOrderInfo.getItemTitle())) {
                            row.createCell(40).setCellValue(oOrderInfo.getItemTitle());
                        }
                        if (isRefund) {
                            if (content.getRefundType() != null && content.getRefundType() == 1) {
                                row.createCell(43).setCellValue("部分退款");
                            } else {
                                row.createCell(43).setCellValue("全部退款");
                            }
                            if (StringUtils.isNotBlank(content.getRefundDesc())) {
                                row.createCell(44).setCellValue(content.getRefundDesc());
                            }
                        }
                        row.createCell(45).setCellValue(content.getDeductionFee());
                        if (Objects.nonNull(oOrderInfo.getDeductionExpire()) && oOrderInfo.getDeductionExpire()) {
                            row.createCell(46).setCellValue(oOrderInfo.getDeductionMoney());
                        }
                        //增加纸质证书领取时间导出
                        if (StringUtils.isNotBlank(oOrderInfo.getCertificateNo())) {
                            query = new Query();
                            query.addCriteria(Criteria.where("certificateNo").is(oOrderInfo.getCertificateNo()));
                            UserCaRecord userCaRecord = this.mongoTemplate.findOne(query, UserCaRecord.class);
                            if (Objects.nonNull(userCaRecord)) {
                                row.createCell(41).setCellValue(userCaRecord.getCaTime());
                            }
                        }
                        if (Objects.nonNull(content.getPayTime())) {
                            String t = TimeUtils.formatDate(content.getPayTime(), "yyyy-MM-dd HH:mm:ss");
                            row.createCell(42).setCellValue(t);
                        }
                        if (Objects.nonNull(content.getVersion())) {
                            row.createCell(65).setCellValue(content.getVersion());
                        }
                        if (Objects.nonNull(caInfo)) {
                            if (Boolean.TRUE.equals(caInfo.getCombinedCommodity())) {
                                row.createCell(52).setCellValue("是");
                                Query queryChild = new Query();
                                queryChild.addCriteria(Criteria.where("parentId").is(caInfo.getId()));
                                List<CaInfo> children = mongoTemplate.find(queryChild, CaInfo.class);
                                if (Objects.isNull(children) || CollectionUtils.isEmpty(children)) {
                                    row.createCell(53).setCellValue("警告数据错误,请立即检查数据!!");
                                } else {
                                    int dd = 53;
                                    for (CaInfo cc : children) {
                                        row.createCell(dd).setCellValue(cc.getName());
                                        dd++;
                                        row.createCell(dd).setCellValue(cc.getId());
                                        dd++;
                                    }
                                }
                            } else {
                                row.createCell(52).setCellValue("否");
                            }
                        }
                        rowNum++;
                    }

                    counter++;
                }
            }

            //将excel写入到输出流中
            log.info(":>>> flush:{} 行", rowNum);
            OutputStream outputStream = new FileOutputStream(fileExportPath + f);
            workbook.write(outputStream);
            outputStream.flush();
            outputStream.close();
            log.info(":>>> 写文件到本地然后读:{}", f);
            File file = new File(fileExportPath + f);
            InputStream in = new FileInputStream(file);
            String url = fileService.uploadFile(in, f);
            Query queryTask = new Query().addCriteria(Criteria.where("id").is(exportTaskId));
            Update update = new Update();
            update.set("url", url);
            update.set("status", 1);
            update.set("updatedTime", new Date());
            UpdateResult updateResult = mongoTemplate.updateFirst(queryTask, update, FileExportTask.class);
            log.info(":>>> 更新任务:{},状态:{}", exportTaskId, updateResult.getModifiedCount() > 0 ? true : false);
            in.close();
            log.info(":>>> 发货订单内容导出,关闭文件流");
        } catch (Exception e) {
            log.error(":>>> 发货订单内容导出错误:{}", e);
        }
    }

        private void exportSingleOrder(String batchId, Query query, Long count, String f, String exportTaskId) {
        HashMap<String, UniversityInfo> universityInfoHashMap = new HashMap<>();
        HashMap<String, ActivityInfo> activityInfoHashMap = new HashMap<>();
        int counter = 0;
        XSSFWorkbook workbook = new XSSFWorkbook();
        HashMap<String, CaInfo> caInfoHashMap = new HashMap<>();
        try {
            int rowNum = 1;
            int sheetNum = 1;
            //创建一个Excel表单,参数为sheet的名字
            XSSFSheet sheet = workbook.createSheet("sheet" + "-" + sheetNum);
            setExpressOrderExcelTitle(workbook, sheet);
            //创建表头
            XSSFRow row = null;
            List<OrderInfo> contents = mongoTemplate.find(query, OrderInfo.class);
            HashMap<String, OrderInfo> orderCache = new HashMap<>();
            if (Objects.isNull(contents) && CollectionUtils.isEmpty(contents)) {
                log.error(":>>> 第:{} 页，数据为空");
                return;
            }
            List<String> orderNos = new ArrayList<>();
            for (OrderInfo orderInfo : contents) {
                if (!StringUtils.isBlank(orderInfo.getOrderNo())) {
                    orderNos.add(orderInfo.getOrderNo());
                    orderCache.put(orderInfo.getOrderNo(), orderInfo);
                }
            }
            Query querySub = new Query().addCriteria(Criteria.where("orderNo").in(orderNos));
//            querySub.with(new Sort(new Sort.Order(Sort.Direction.ASC, "singleNo")));
            Sort sort = Sort.by(Sort.Direction.DESC, "singleNo");
            querySub.with(sort);
            List<OOrderInfo> subs = mongoTemplate.find(querySub, OOrderInfo.class);
            List<OOrderInfo> todo = new ArrayList<>();
            int j = 0;
            // 排序
            for (OOrderInfo oOrderInfo : subs) {
                if (StringUtils.isBlank(oOrderInfo.getItemInfoId())) {
                    log.error("子订单:{} 没有配置商品，严重警告", oOrderInfo.getOOrderNo());
                    continue;
                }
                CaInfo caInfo = caInfoHashMap.get(oOrderInfo.getItemInfoId());
                if (Objects.isNull(caInfo)) {
                    caInfo = caInfoService.findOne(oOrderInfo.getItemInfoId());
                    if (Objects.nonNull(caInfo)) {
                        caInfoHashMap.put(oOrderInfo.getItemInfoId(), caInfo);
                    }
                }
                if (Boolean.TRUE.equals(oOrderInfo.getCaGift())) {
                    oOrderInfo.setSinglePriority(2);
                } else {
                    oOrderInfo.setSinglePriority(1);
                }
            }
//            Collections.sort(subs);
            for (OOrderInfo oOrderInfo : subs) {
                String singleNo = oOrderInfo.getSingleNo();
                log.info(":>>> 子订单:{},合单ID:{}", oOrderInfo.getId(), singleNo);
                List<OOrderInfo> ss = new ArrayList<>();
                ss.add(oOrderInfo);
                for (int i = j; i < subs.size() - 1; i++) {
                    if (StringUtils.isNotBlank(singleNo)) {
                        if (singleNo.equals(subs.get(i + 1).getSingleNo())) {
                            ss.add(subs.get(i + 1));
                            log.info(":>>> 子订单:{},合单关联订单:{}", oOrderInfo.getId(), subs.get(i + 1).getId());
                        } else {
                            break;
                        }
                    }
                }
                Collections.sort(ss);
                oOrderInfo.setSubSingleOrders(ss);
                todo.add(oOrderInfo);
                j++;
            }
            String address = "";
            log.info(":>>> 开始导出合单订单数量:{}", todo.size());
            List<String> delete = new ArrayList<>();
            Collections.sort(todo);
            for (OOrderInfo oOrderInfo : todo) {
                if (delete.contains(oOrderInfo.getId())) {
                    continue;
                }
                delete.add(oOrderInfo.getId());
                String g = "";
                OrderInfo content = orderCache.get(oOrderInfo.getOrderNo());
                CaInfo caInfo = null;
                if (StringUtils.isNotBlank(oOrderInfo.getItemInfoId())) {
                    if (caInfoHashMap.containsKey(oOrderInfo.getItemInfoId())) {
                        caInfo = caInfoHashMap.get(oOrderInfo.getItemInfoId());
                    } else {
                        caInfo = caInfoService.findCaInfoById(oOrderInfo.getItemInfoId());
                        caInfoHashMap.put(oOrderInfo.getItemInfoId(), caInfo);
                    }

                }
                log.info(":>>> 导出行数:{}", counter);
                if (counter != 0 && counter % 990000 == 0) {
                    //超过990000就自动创建一个sheet
                    sheetNum++;
                    sheet = workbook.createSheet("sheet-" + sheetNum);
                    setExpressOrderExcelTitle(workbook, sheet);
                    //创建表头
                    //新增数据行，并且设置单元格数据
                    rowNum = 1;
                    sheetNum++;
                    log.info(":>>> 操作600000行,创建新sheet");
                }
                row = sheet.createRow(rowNum);
                boolean gift = false;
                // 礼品 第一列
                if (Objects.nonNull(caInfo)) {
                    if (CollectionUtils.isNotEmpty(oOrderInfo.getSubSingleOrders())) {
                        g = "";
                        for (OOrderInfo o : oOrderInfo.getSubSingleOrders()) {
                            if (!delete.contains(o.getId())) {
                                delete.add(o.getId());
                            }
                            delete.add(oOrderInfo.getId());
                            CaInfo c = caInfoService.findCaInfoById(o.getItemInfoId());
                            caInfoHashMap.put(o.getItemInfoId(), c);
//                            if (Boolean.TRUE.equals(c.getCaGift())) {
                            if (Boolean.TRUE.equals(c.getCaGift()) && StringUtils.isNotBlank(c.getMaterialConfigId())) {
                                CaMaterialConfig config = caMaterialConfigService.findOne(c.getMaterialConfigId());
                                if (Objects.nonNull(config)) {
                                    if (StringUtils.isNotBlank(g)) {
                                        g = g + "+" + config.getName();
                                    } else {
                                        g = config.getName();
                                    }
                                }
                            }

                            if (2 == c.getItemType() && CollectionUtils.isNotEmpty(c.getItemMaterialList())) {
                                for (String itemMaterialId : c.getItemMaterialList()) {
                                    CaMaterialConfig config = caMaterialConfigService.findOne(itemMaterialId);
                                    if (Objects.nonNull(config)) {
                                        if (StringUtils.isNotBlank(g)) {
                                            g = g + "+" + config.getName();
                                        } else {
                                            g = config.getName();
                                        }
                                    }

                                }

                            }
//                            }

                        }
                        if (StringUtils.isNotBlank(g)) {
                            row.createCell(0).setCellValue(g);
                            gift = true;
                            row.createCell(25).setCellValue("否");
                        }
                    }
                }
                if (!gift) {
                    // 礼品 第一列
                    if (Objects.nonNull(oOrderInfo) && StringUtils.isNotBlank(oOrderInfo.getGift())) {
                        String g1 = oOrderInfo.getGift().replace("<P>", "");
                        g1 = g1.replace("</p>", "");
                        g1 = g1.replace("<p>", "");
                        row.createCell(0).setCellValue(g1);
                        row.createCell(26).setCellValue(g1);
                    }
                }

                // 证书材质 第2列
                // 2021-05-28 00:36:07 之后版本更新了
                if (Objects.nonNull(caInfo)) {
                    if (content.getCreatedTime().after(new Date(1622133367000L))) {
                        List<String> itemMaterialIdList = caInfo.getItemMaterialList();
                        if (CollectionUtils.isNotEmpty(itemMaterialIdList)) {
                            List<CaMaterialConfig> caMaterialIdList =
                                    caMaterialConfigService.findByCaMaterialIdList(itemMaterialIdList);
                            if (CollectionUtils.isNotEmpty(caMaterialIdList)) {
                                String name =
                                        caMaterialIdList.stream().map(CaMaterialConfig::getName).collect(Collectors.joining(
                                                ","));
                                row.createCell(1).setCellValue(name);
                                if (g.contains(name + "+")) {
                                    g = g.replace(name + "+", "");
                                    if (StringUtils.isNotBlank(g)) {
                                        row.createCell(0).setCellValue(g);
                                        gift = true;
                                        row.createCell(25).setCellValue("否");
                                    }
                                } else if (g.contains(name)) {
                                    g = g.replace(name, "");
                                    if (StringUtils.isNotBlank(g)) {
                                        row.createCell(0).setCellValue(g);
                                        gift = true;
                                        row.createCell(25).setCellValue("否");
                                    }
                                }
                            } else {
                                if (StringUtils.isNotBlank(caInfo.getEdition())) {
                                    row.createCell(1).setCellValue(caInfo.getEdition());
                                }
                            }
                        } else {
                            CaMaterialConfig config = caMaterialConfigService.findOne(caInfo.getMaterialConfigId());
                            if (Objects.nonNull(config) && StringUtils.isNotBlank(config.getName())) {
                                row.createCell(1).setCellValue(config.getName());
                                if (g.contains(config.getName() + "+")) {
                                    g = g.replace(config.getName() + "+", "");
                                    if (StringUtils.isNotBlank(g)) {
                                        row.createCell(0).setCellValue(g);
                                        gift = true;
                                        row.createCell(25).setCellValue("否");
                                    }
                                } else if (g.contains(config.getName())) {
                                    g = g.replace(config.getName(), "");
                                    if (StringUtils.isNotBlank(g)) {
                                        row.createCell(0).setCellValue(g);
                                        gift = true;
                                        row.createCell(25).setCellValue("否");
                                    }
                                }
                            } else {
                                if (StringUtils.isNotBlank(caInfo.getEdition())) {
                                    row.createCell(1).setCellValue(caInfo.getEdition());
                                }
                            }
                        }


                        if (StringUtils.isNotBlank(caInfo.getLevel())) {
                            row.createCell(2).setCellValue(caInfo.getLevel());
                        }

                    }
                } else {
                    if (Objects.nonNull(oOrderInfo) && StringUtils.isNotBlank(oOrderInfo.getItemTitle())) {
                        String[] splitAddress = oOrderInfo.getItemTitle().split("，");

                        if (splitAddress.length == 3) {
                            row.createCell(1).setCellValue(splitAddress[2]);
                            row.createCell(2).setCellValue(splitAddress[1]);
                        } else if (splitAddress.length == 2) {
                            row.createCell(1).setCellValue(splitAddress[1]);
                        }

                    }
                }
                log.info(":>>> 大学ID:{}", content.getUniversityId());
                if (StringUtils.isNotBlank(content.getUniversityId())) {
                    if (universityInfoHashMap.containsKey(content.getUniversityId())) {
                        row.createCell(3).setCellValue(universityInfoHashMap.get(content.getUniversityId()).getName());
                    } else {
                        Query query1 = new Query().addCriteria(Criteria.where("id").is(content.getUniversityId()));
                        UniversityInfo universityInfo = mongoTemplate.findOne(query1, UniversityInfo.class);
                        if (Objects.nonNull(universityInfo)) {
                            row.createCell(3).setCellValue(universityInfo.getName());
                            universityInfoHashMap.put(content.getUniversityId(), universityInfo);
                        }
                    }
                }
                // 证书打印名字 第5列
                if (Objects.nonNull(content.getCaPrintName())) {
                    row.createCell(4).setCellValue(content.getCaPrintName());
                }
                // 证书编号 第6列
                if (StringUtils.isNotBlank(oOrderInfo.getCertificateNo())) {
                    row.createCell(5).setCellValue(oOrderInfo.getCertificateNo());
                }
                // 姓名 第7列
                if (StringUtils.isNotBlank(content.getName())) {
                    row.createCell(6).setCellValue(content.getName());
                }
                // 电话 第8列
                if (StringUtils.isNotBlank(content.getMobile())) {
                    row.createCell(7).setCellValue(content.getMobile());
                }
                // 省 第9列
                if (StringUtils.isNotBlank(content.getProvince())) {
                    row.createCell(8).setCellValue(content.getProvince());
                }
                // 市 第10列
                if (StringUtils.isNotBlank(content.getCity())) {
                    row.createCell(9).setCellValue(content.getCity());
                }
                // 区 第11列
                if (StringUtils.isNotBlank(content.getArea())) {
                    row.createCell(10).setCellValue(content.getArea());
                }
                // 地址 第12列
                if (StringUtils.isNotBlank(content.getAddress())) {
                    address = filterAddress(content.getAddress(), content.getProvince(), content.getCity(),
                            content.getArea(), content.getMobile());
                    if (StringUtils.isNotBlank(address)) {
                        row.createCell(11).setCellValue(address);
                    }
                }
                // 是否需要合单 第13列
                if (CollectionUtils.isNotEmpty(oOrderInfo.getSubSingleOrders())) {
                    row.createCell(12).setCellValue("是");
                } else {
                    row.createCell(12).setCellValue("否");
                }
                // 订单编号 第14列
                if (StringUtils.isNotBlank(content.getOrderNo())) {
                    row.createCell(13).setCellValue(content.getOrderNo());
                }
                // 子订单编号 第14列
                if (StringUtils.isNotBlank(oOrderInfo.getOOrderNo())) {
                    row.createCell(14).setCellValue(oOrderInfo.getOOrderNo());
                }
                // 微信交易号 第16列
                if (Objects.nonNull(content.getTransactionId())) {
                    row.createCell(15).setCellValue(content.getTransactionId());
                }
                // 订单标识 第17列
                if (StringUtils.isNotBlank(content.getId())) {
                    row.createCell(16).setCellValue(content.getId());
                }
                // 平台 第18列
                if (StringUtils.isNotBlank(content.getPlatform())) {
                    row.createCell(17).setCellValue(content.getPlatform());
                }
                if (StringUtils.isNotBlank(content.getOpenId())) {
                    row.createCell(18).setCellValue(content.getOpenId());
                    Query queryWechatUser = new Query().addCriteria(Criteria.where("openId").is(content.getOpenId()));
                    WechatH5UserPO wechatH5UserPO = mongoTemplate.findOne(queryWechatUser, WechatH5UserPO.class);
                    if (Objects.nonNull(wechatH5UserPO) && StringUtils.isNotBlank(wechatH5UserPO.getUnionId())) {
                        row.createCell(19).setCellValue(wechatH5UserPO.getUnionId());
                    }
                }
                if (StringUtils.isNotBlank(content.getActivityId())) {
                    ActivityInfo activityInfo = null;
                    if (activityInfoHashMap.containsKey(content.getActivityId())) {
                        activityInfo = activityInfoHashMap.get(content.getActivityId());
                    } else {
                        Query queryA = new Query().addCriteria(Criteria.where("id").is(content.getActivityId()));
                        activityInfo = mongoTemplate.findOne(queryA, ActivityInfo.class);
                        if (Objects.nonNull(activityInfo)) {
                            activityInfoHashMap.put(content.getActivityId(), activityInfo);
                        }
                    }

                    if (Objects.nonNull(activityInfo) && StringUtils.isNotBlank(activityInfo.getName())) {
                        row.createCell(20).setCellValue(activityInfo.getName());
                    }
                }
                // 是否有礼品 第21列
                if (Objects.nonNull(caInfo)) {
                    if (Objects.nonNull(caInfo.getCaGift())) {
                        if (Boolean.TRUE.equals(caInfo.getCaGift())) {
                            row.createCell(21).setCellValue("是");
                        } else {
                            row.createCell(21).setCellValue("否");
                        }
                    }
                } else {
                    if (Objects.nonNull(oOrderInfo.getCaGift())) {
                        if (Boolean.TRUE.equals(oOrderInfo.getCaGift())) {
                            row.createCell(21).setCellValue("是");
                        } else {
                            row.createCell(21).setCellValue("否");
                        }
                    }
                }
                // 订单状态
                String caStatusStr = this.getOrderStatusStr(content.getStatus());
                log.info(":>>> 订单状态:{}", caStatusStr);
                row.createCell(22).setCellValue(caStatusStr);
                if (StringUtils.isNotBlank(oOrderInfo.getLogisticsCompany())) {
                    row.createCell(23).setCellValue(oOrderInfo.getLogisticsCompany());
                }
                if (StringUtils.isNotBlank(oOrderInfo.getLogisticsNo())) {
                    row.createCell(24).setCellValue(oOrderInfo.getLogisticsNo());
                }
                if (Objects.nonNull(oOrderInfo.getOverbought())) {
                    row.createCell(27).setCellValue(oOrderInfo.getOverbought());
                }
                // 29列合单ID
                if (Objects.nonNull(oOrderInfo.getSingleNo())) {
                    row.createCell(29).setCellValue(oOrderInfo.getSingleNo());
                }
                // 30列合单ID
                if (Objects.nonNull(oOrderInfo.getSingleOrderBatchId())) {
                    row.createCell(30).setCellValue(oOrderInfo.getSingleOrderBatchId());
                }
                // 31列合单ID
                if (CollectionUtils.isNotEmpty(oOrderInfo.getSubSingleOrders())) {
                    row.createCell(31).setCellValue(oOrderInfo.getSubSingleOrders().size());
                } else {
                    row.createCell(31).setCellValue(1);
                }
                rowNum++;
                counter++;
            }

            counter++;
            //将excel写入到输出流中
            log.info(":>>> flush:{} 行", rowNum);
            OutputStream outputStream = new FileOutputStream(fileExportPath + f);
            workbook.write(outputStream);
            outputStream.flush();
            outputStream.close();
            log.info(":>>> 写文件到本地然后读:{}", f);
            File file = new File(fileExportPath + f);
            InputStream in = new FileInputStream(file);
            String url = fileService.uploadFile(in, f);
            Query queryTask = new Query().addCriteria(Criteria.where("id").is(exportTaskId));
            Update update = new Update();
            update.set("url", url);
            update.set("status", 1);
            update.set("updatedTime", new Date());
            UpdateResult updateResult = mongoTemplate.updateFirst(queryTask, update, FileExportTask.class);
            log.info(":>>> 更新任务:{},状态:{}", exportTaskId, updateResult.getModifiedCount() > 0 ? true : false);
            Query queryBatch = new Query().addCriteria(Criteria.where("id").is(batchId));
            Update update1 = new Update();
            update1.set("fileUrl", url);
            update1.set("updatedTime", new Date());
            mongoTemplate.updateFirst(queryBatch, update1, SingleOrderBatch.class);
            in.close();
            log.info(":>>> 合单订单内容导出,关闭文件流");
        } catch (Exception e) {
            log.error(":>>> 合单订单内容导出错误:{}", e);
        }
    }

        private void exportRefundOrder(String batchId, Query query, Long count, String f, String exportTaskId) {
        int counter = 0;
        XSSFWorkbook workbook = new XSSFWorkbook();
        try {
            int rowNum = 1;
            int sheetNum = 1;
            //创建一个Excel表单,参数为sheet的名字
            XSSFSheet sheet = workbook.createSheet("sheet" + "-" + sheetNum);
            setExpressOrderExcelTitle(workbook, sheet);
            //创建表头
            XSSFRow row = null;
            List<OrderInfo> contents = mongoTemplate.find(query, OrderInfo.class);
            for (OrderInfo content : contents) {
                row = sheet.createRow(rowNum);
                //if (counter != 0 && counter % 990000 == 0) {
                //超过990000就自动创建一个sheet
                //创建表头
                //新增数据行，并且设置单元格数据
                Date date = content.getRefundTime();
                if (Objects.isNull(date)) {
                    date = content.getUpdatedTime();
                }
                if (Objects.nonNull(date)) {
                    String dateNowStr = TimeUtils.parse(date, "yyyy-MM-dd HH:mm:ss");
                    row.createCell(0).setCellValue(dateNowStr);
                }
                // 订单编号 第1列
                if (StringUtils.isNotBlank(content.getOrderNo())) {
                    row.createCell(1).setCellValue(content.getOrderNo());
                }
                if (StringUtils.isNotBlank(content.getActivityId())) {
                    ActivityInfo activityInfo = activityService.findOne(content.getActivityId());
                    row.createCell(2).setCellValue(activityInfo.getName());
                }
                if (StringUtils.isNotBlank(content.getName())) {
                    row.createCell(3).setCellValue(content.getName());
                }
                if (StringUtils.isNotBlank(content.getMobile())) {
                    row.createCell(4).setCellValue(content.getMobile());
                }
                if (StringUtils.isNotBlank(content.getLogisticsNo())) {
                    row.createCell(5).setCellValue("已发货");
                } else {
                    row.createCell(5).setCellValue("未发货");
                }
                if (StringUtils.isNotBlank(content.getRefundWay())) {
                    row.createCell(7).setCellValue(content.getRefundWay());
                }
                if (Objects.nonNull(content.getRefundFee())) {
                    row.createCell(8).setCellValue(content.getRefundFee());
                }
                if (StringUtils.isNotBlank(content.getOptName())) {
                    row.createCell(9).setCellValue(content.getOptName());
                }
                //退款申请时间
                if (Objects.nonNull(content.getRefundApplyTime())) {
                    String dateNowStr = TimeUtils.parse(content.getRefundApplyTime(), "yyyy-MM-dd " +
                            "HH:mm:ss");
                    row.createCell(10).setCellValue(dateNowStr);
                }
                // 退款备注
                if (Objects.nonNull(content.getRefundComment())) {
                    row.createCell(11).setCellValue(content.getRefundComment());
                }
                if (StringUtils.isNotBlank(content.getVerifyOptName())) {
                    row.createCell(12).setCellValue(content.getVerifyOptName());
                }
                if (StringUtils.isNotBlank(content.getUniversityName())) {
                    row.createCell(13).setCellValue(content.getUniversityName());
                }
                rowNum++;
            }
            //将excel写入到输出流中
            log.info(":>>> flush:{} 行", rowNum);
            OutputStream outputStream = new FileOutputStream(fileExportPath + f);
            workbook.write(outputStream);
            outputStream.flush();
            outputStream.close();
            log.info(":>>> 写文件到本地然后读:{}", f);
            File file = new File(fileExportPath + f);
            InputStream in = new FileInputStream(file);
            String url = fileService.uploadFile(in, f);
            Query queryTask = new Query().addCriteria(Criteria.where("id").is(exportTaskId));
            Update update = new Update();
            update.set("url", url);
            update.set("status", 1);
            update.set("updatedTime", new Date());
            UpdateResult updateResult = mongoTemplate.updateFirst(queryTask, update, FileExportTask.class);
            log.info(":>>> 更新任务:{},状态:{}", exportTaskId, updateResult.getModifiedCount() > 0 ? true : false);
            in.close();
            log.info(":>>> 退款订单内容导出,关闭文件流");
        } catch (Exception e) {
            log.error(":>>> 退款订单内容导出错误:{}", e);
        }
    }


    private boolean checkShipInfo(String orderNo, String logisticsNo, String logisticsCompany) {
        if (!orderNo.contains("20")) {
            log.error(":>>> 订单编号不包含20字样");
            return false;
        }
        if ("#N/A".equals(logisticsNo) || "#N/A".equals(logisticsCompany)) {
            log.error(":>>> 物流单号包含空:#N/A");
            return false;
        }
        if (logisticsNo.length() < 5) {
            log.error(":>>> 物流单号长度小于5为");
            return false;
        }
        if (!logisticsCompany.contains("快递") && !logisticsCompany.contains("申通") && !logisticsCompany.contains("圆通") && !logisticsCompany.contains("邮政") && !logisticsCompany.contains("EMS") && !logisticsCompany.contains("顺丰")
                && !logisticsCompany.contains("天天") && !logisticsCompany.contains("百世") && !logisticsCompany.contains("京东") && !logisticsCompany.contains("韵达") && !logisticsCompany.contains("中通")) {
            log.error(":>>> 物流公司不在制定物流列表");
            return false;
        }
        return true;
    }

    private void setOrderTipsNes(OrderInfo orderInfo) {
        if (Objects.isNull(orderInfo) || StringUtils.isBlank(orderInfo.getStatus())) {
            return;
        }
        String tips = "";
        if (StringUtils.isNotBlank(orderInfo.getRefundStatus())) {
            switch (orderInfo.getRefundStatus()) {
                case "2":
                    tips = "退款申请成功，原订单金额将于1-3个工作日到账，注意查收！";
                    orderInfo.setTips(tips);
                    return;
                case "3":
                    tips = "用户申请退款,退款完成,请查看微信账单!";
                    orderInfo.setTips(tips);
                    return;
                default:
                    break;
            }
        }

        if ("1".equals(orderInfo.getStatus())) {
            tips = "亲，您的订单需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
            if (Objects.nonNull(orderInfo.getPayTime())) {
//                Date d = TimeUtils.getDayEndTime(orderInfo.getPayTime());
//                Date d = new Date(orderInfo.getPayTime().getTime() + 12 * 3600 * 1000L);
                if ((new Date().getTime() - orderInfo.getPayTime().getTime()) > 12 * 3600 * 1000L) {
                    orderInfo.setStatus("2");
                    tips = "亲，您的订单目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
                }
            }
            OrderInfoTip orderInfoTip = orderInfoTipService.find(orderInfo.getOrderNo());
            if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                tips = orderInfoTip.getTips();
                log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
            }

        } else if ("2".equals(orderInfo.getStatus())) {
            OrderInfoTip orderInfoTip = orderInfoTipService.find(orderInfo.getOrderNo());
            if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                tips = orderInfoTip.getTips();
                log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
            }
            if (StringUtils.isBlank(tips)) {
                tips = "亲，您的订单目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";

            }

        } else if ("3".equals(orderInfo.getStatus())) {
            tips = "亲，您的订单目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
        } else if ("4".equals(orderInfo.getStatus())) {
            OrderInfoTip orderInfoTip = orderInfoTipService.find(orderInfo.getOrderNo(), Boolean.TRUE);
            if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                tips = orderInfoTip.getTips();
                log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
            } else {
                tips = "您的订单已经发货，请注意查收！可点击下方按钮查看物流进度";
            }

//            tips = "您的订单已经发货，请注意查收！可点击下方按钮查看物流进度";
        }
        orderInfo.setTips(tips);
    }

    /**
     * status 状态,0:待付款,1:已付款,2:制作中,3:待发货,4:待收货,5:已收货,6:订单完成,7:订单关闭,8:售后中,9:部分已发货
     * refundStatus 退款状态,0:未退款,1:退款申请,2:退款中,3:退款完成,4:待返货,7:部分退款中
     */

    private void setOrderTips(OrderInfo orderInfo) {
        if (Objects.isNull(orderInfo) || StringUtils.isBlank(orderInfo.getStatus())) {
            return;
        }
        String tips = "";
        if (StringUtils.isNotBlank(orderInfo.getRefundStatus())) {
            switch (orderInfo.getRefundStatus()) {
                case "2":
                    tips = "用户申请退款,审核中,将在3个工作日内到账!";
                    orderInfo.setTips(tips);
                    return;
                case "3":
                    tips = "用户申请退款,退款完成,请查看微信账单!";
                    orderInfo.setTips(tips);
                    return;
                default:
                    break;
            }
        }

        if ("1".equals(orderInfo.getStatus())) {
            tips = "亲,您的订单需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，发货后会有物流单号在这里显示哦～";
            if (Objects.nonNull(orderInfo.getPayTime())) {
                Date d = TimeUtils.getDayEndTime(orderInfo.getPayTime());
                if (new Date().after(d)) {
                    orderInfo.setStatus("2");
                }
            }
            OrderInfoTip orderInfoTip = orderInfoTipService.find(orderInfo.getOrderNo());
            if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                tips = orderInfoTip.getTips();
                log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
            }
        } else if ("4".equals(orderInfo.getStatus())) {
            tips = "您的订单已经发货，请注意查收！可点击下方按钮查看物流进度";
        }
        orderInfo.setTips(tips);
    }


    private Boolean doRefund2(QQWxRefundRequest request, RefundOrderResult refundResult, List<String> merchantIds,
                              String platform) {
        if ("SUCCESS".equals(refundResult.getResult_code())) {
            return Boolean.TRUE;
        }
        //订单号不存在，随机循环取那
        if ("ORDERNOTEXIST".equals(refundResult.getErr_code()) && "FAIL".equals(refundResult.getResult_code())) {
            Integer randomMerchantId = random(merchantIds.size());
            log.error("【退款随机商户号id 】->{}", randomMerchantId);
            QQWxRefundRequest wxRefundRequest = new QQWxRefundRequest();
            BeanUtils.copyProperties(request, wxRefundRequest);
            wxRefundRequest.setMerchantId(merchantIds.get(randomMerchantId));
            wxRefundRequest.setOrderMerchantId(merchantIds.get(randomMerchantId));
            RefundOrderResult result = refund(wxRefundRequest, platform);
            if ("SUCCESS".equals(result.getResult_code())) {
                return Boolean.TRUE;
            }
            if ("ORDERNOTEXIST".equals(result.getErr_code()) && "FAIL".equals(result.getResult_code())) {
                return doRefund2(request, result, merchantIds, platform);
            }
            if (Objects.isNull(result) || !"SUCCESS".equals(result.getResult_code())) {
                log.error(":>>> 订单:{},退款失败:{}", result.getErr_code_des());
                return false;
            }
        }
        if (Objects.isNull(refundResult) || !"SUCCESS".equals(refundResult.getResult_code())) {
            log.error(":>>> 订单:{},退款失败:{}", refundResult.getErr_code_des());
            return false;
        }
        return Boolean.TRUE;
    }

    /**
     * 处理审核通过
     *
     * @param req
     * @param orderInfo
     * @param subOrders
     * @return
     */
    @Override
    public boolean doRefundPassVerify(OrderRefundOptVO req, OrderInfo orderInfo, List<OOrderInfo> subOrders) {
        //                退款方式,one-line:线上,off-line:线下
        Date date = new Date();
        Query query = new Query().addCriteria(Criteria.where("id").is(orderInfo.getId()));
        Integer refundFee = 0;
        if (orderInfo.getRefundType() != null && orderInfo.getRefundType() == 1) {
            refundFee = orderInfo.getRefundFee();
        } else {
            refundFee = orderInfo.getTotalFee();
        }
        switch (req.getRefundWay()) {
            case "on-line": {
                //包含兑换码的，12小时不能走线上 12小时之内，要取消兑换码
                tsCardService.disuseRedeemCode(orderInfo);
                Integer expressFee = 0;
//                for (OOrderInfo oOrderInfo : subOrders) {
//                    if (Objects.nonNull(orderInfo.getExpressFee())) {
//                        expressFee = orderInfo.getExtraExpressFee() + orderInfo.getExpressFee() / subOrders.size();
//                    }
//                    refundFee = refundFee + oOrderInfo.getSalePrice() + expressFee;
//                }
                QQWxRefundRequest request = new QQWxRefundRequest();
                request.setAppId(orderInfo.getAppId());
                request.setOpenId(orderInfo.getOpenId());
                request.setOrderNo(orderInfo.getOrderNo());
                request.setRefundFee(refundFee);
                request.setDesc("商品退款");
                request.setTotalFee(orderInfo.getTotalFee());
                request.setOrderMerchantId(orderInfo.getMechantId());
                String refundNo = generateRefundOrderNo("ca-order.refund.no");
                request.setRefundNo(refundNo);
                request.setWechatAppId(orderInfo.getWechatAppId());
                request.setPlatform(orderInfo.getPlatform());
                switch (orderInfo.getPlatform()) {
                    case "qq":
                        QQConfigInfo qqConfigInfo = qqConfigInfoService.findByAppId(orderInfo.getAppId());
                        req.getMerchantIds().add(qqConfigInfo.getMerchantId());
                        break;
                    case "wechat-h5":
                        WechatConfigInfo wechatConfigInfo = wechatConfigInfoService.find(orderInfo.getAppId());
                        req.setMerchantIds(wechatConfigInfo.getMerchantIds());
                        break;
                    default:
                        break;
                }
                Boolean successRefund;
                if ("wechat-mini".equals(orderInfo.getPlatform())) {
                    WechatMerchantConfig wechatMerchantConfig =
                            wechatMerchantConfigService.findByMerchantIdAndDecrypt(orderInfo.getMechantId());
                    if (Objects.isNull(wechatMerchantConfig)) {
                        return Boolean.FALSE;
                    }
                    GoodsOrderDTO goodsOrderDTO = new GoodsOrderDTO();
                    goodsOrderDTO.setOrderNo(orderInfo.getOrderNo());
                    goodsOrderDTO.setClientIp(orderInfo.getClientIp());
                    goodsOrderDTO.setOpenId(orderInfo.getOpenId());
                    goodsOrderDTO.setGoodsName(orderInfo.getOrderNo());
                    goodsOrderDTO.setPrice(orderInfo.getTotalFee());
                    goodsOrderDTO.setRefundPrice(refundFee);
                    goodsOrderDTO.setUserId(orderInfo.getAccountInfoId());
                    goodsOrderDTO.setAppId(orderInfo.getAppId());
                    goodsOrderDTO.setRefundNo(refundNo);
                    successRefund = this.wxMinirefund(goodsOrderDTO, wechatMerchantConfig);
                } else {
                    RefundOrderResult refundResult = this.refund(request, orderInfo.getPlatform());
                    log.info(":>>> 订单:{},退款结果:{}", orderInfo.getOrderNo(), JSON.toJSONString(refundResult));
                    successRefund = doRefund2(request, refundResult, req.getMerchantIds(), orderInfo.getPlatform());
                }
//                RefundOrderResult refundResult = this.refund(request, orderInfo.getPlatform());
//                log.info(":>>> 订单:{},退款结果:{}", orderInfo.getOrderNo(), JSON.toJSONString(refundResult));
//                Boolean successRefund = doRefund2(request, refundResult, req.getMerchantIds(), orderInfo
//                .getPlatform());
                if (!successRefund) {
                    return Boolean.FALSE;
                }

                for (OOrderInfo oOrderInfo : subOrders) {
                    Query query1 = new Query().addCriteria(Criteria.where("id").is(oOrderInfo.getId()));
                    Update update = new Update();
                    update.set("verifyStatus", 2);
                    update.set("refundStatus", "3");
                    update.set("refundId", refundNo);
                    update.set("updatedTime", date);
                    update.set("refundTime", date);
                    update.set("status", "6");
                    FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
                    findAndModifyOptions.returnNew(Boolean.TRUE);
                    findAndModifyOptions.upsert(Boolean.TRUE);
                    OOrderInfo subModify = mongoTemplate.findAndModify(query1, update, findAndModifyOptions,
                            OOrderInfo.class);
                    if (Objects.nonNull(subModify)) {
                        cacheCaInfoService.putAndGetItemStock(oOrderInfo.getItemInfoId(), -1L);
                    }
                    userPurchaseCaService.deleteItemBuyRecord(orderInfo.getActivityId(), orderInfo.getAccountInfoId(),
                            oOrderInfo.getItemInfoId());
                    userPurchaseCaService.deleteCategoryBuyRecord(orderInfo.getActivityId(), orderInfo.getAccountInfoId(),
                            oOrderInfo.getItemInfoId());
                }
                Update update = new Update();
                update.set("verifyStatus", 2);
                update.set("refundStatus", "3");
                update.set("refundId", refundNo);
                update.set("refundFee", refundFee);
                update.set("updatedTime", new Date());
                update.set("refundTime", date);
                update.set("refundComment", req.getRefundComment());
                // 订单完成
                update.set("status", "6");
                update.set("refundWay", req.getRefundWay());
                update.set("refundPayChannel", req.getRefundPayChannel());
                update.set("verifyOptName", req.getOptName());
                UpdateResult updateResult = mongoTemplate.updateFirst(query, update, OrderInfo.class);
                log.info(":>>> 订单:{} 的退款操作结果:{}", req.getId(), updateResult.getModifiedCount() > 0 ? true : false);
                // 发送短信通知
//                String[] params = new String[1];
//                params[0] = orderInfo.getOrderNo();
//                this.sendRefundMsg(orderInfo.getMobile(), orderInfo.getActivityId(), params);
                orderStatisticsService.updateRefundStatistics(orderInfo.getOrderNo(), subOrders);


                ActivityStatistics r = new ActivityStatistics();
                r.setRefundOrderNum(1);
                int refundItemNum = subOrders.stream().mapToInt(OOrderInfo::getNum).sum();
                r.setRefundItemNum(refundItemNum);
                r.setRefundGmv(Double.valueOf(refundFee == null ? 0 : refundFee) / 100);
                activityStatisticsService.increActivityStatistics(orderInfo.getActivityId(), r);
                if (updateResult.getModifiedCount() > 0) {
                    DingTalkRobotRequest dingTalkRobotRequest = new DingTalkRobotRequest();
                    dingTalkRobotRequest.setOptUser(req.getOptName());
                    dingTalkRobotRequest.setTitle(req.getSourcePlatform());
                    dingTalkRobotRequest.setContent(orderInfo.getOrderNo());
                    dingTalkRobotRequest.setModel("订单-退款");
                    dingTalkService.sendBusniessDingTalkMarkdownMsg(dingTalkRobotRequest);
                    //去除更新分账
                    merchantSharingProfitService.doRefund(orderInfo.getOrderNo());
                }
                return updateResult.getModifiedCount() > 0 ? true : false;
            }
            case "off-line": {
//                Integer expressFee = 0;
//                for (OOrderInfo oOrderInfo : subOrders) {
//                    if (Objects.nonNull(orderInfo.getExpressFee())) {
//                        expressFee = orderInfo.getExtraExpressFee() + orderInfo.getExpressFee() / subOrders.size();
//                    }
//                    refundFee = refundFee + oOrderInfo.getSalePrice() + expressFee;
//                }
                for (OOrderInfo oOrderInfo : subOrders) {
                    Query query1 = new Query().addCriteria(Criteria.where("id").is(oOrderInfo.getId()));
                    Update update = new Update();
                    update.set("verifyStatus", 2);
                    update.set("refundStatus", "3");
                    update.set("updatedTime", date);
                    update.set("refundTime", date);
                    FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
                    findAndModifyOptions.returnNew(Boolean.TRUE);
                    findAndModifyOptions.upsert(Boolean.TRUE);
                    OOrderInfo subModify = mongoTemplate.findAndModify(query1, update, findAndModifyOptions,
                            OOrderInfo.class);
                    if (Objects.nonNull(subModify)) {
                        cacheCaInfoService.putAndGetItemStock(oOrderInfo.getItemInfoId(), -1L);
                    }
                }
                Update update = new Update();
                update.set("verifyStatus", 2);
                update.set("refundStatus", "3");
                update.set("refundFee", refundFee);
                update.set("updatedTime", new Date());
                update.set("refundTime", date);
                update.set("refundComment", req.getRefundComment());
                // 订单完成
                update.set("status", "6");
                update.set("refundWay", req.getRefundWay());
                update.set("refundPayChannel", req.getRefundPayChannel());
                update.set("verifyOptName", req.getOptName());
                UpdateResult updateResult = mongoTemplate.updateFirst(query, update, OrderInfo.class);
                log.info(":>>> 订单:{} 的退款操作结果:{}", req.getId(), updateResult.getModifiedCount() > 0 ? true : false);
                orderStatisticsService.updateRefundStatistics(orderInfo.getOrderNo(), subOrders);
                ActivityStatistics r = new ActivityStatistics();
                r.setRefundOrderNum(1);
                int refundItemNum = subOrders.stream().mapToInt(OOrderInfo::getNum).sum();
                r.setRefundItemNum(refundItemNum);
                r.setRefundGmv(Double.valueOf(refundFee == null ? 0 : refundFee) / 100);
                activityStatisticsService.increActivityStatistics(orderInfo.getActivityId(), r);
                if (updateResult.getModifiedCount() > 0) {
                    //去除更新分账
                    merchantSharingProfitService.doRefund(orderInfo.getOrderNo());
                }
                return updateResult.getModifiedCount() > 0 ? true : false;
            }
            default:
                return false;

        }
    }

    /**
     * 处理审核拒绝
     *
     * @param req
     * @param orderInfo
     * @return
     */
    private boolean doRefunfRejectVerify(OrderRefundOptVO req, OrderInfo orderInfo) {
        Query query = new Query().addCriteria(Criteria.where("id").is(orderInfo.getId()));
        Update updateOrder = new Update();
        updateOrder.set("verifyStatus", 0);
        updateOrder.set("status", "1");
        updateOrder.set("refundFee", 0);
        updateOrder.set("refundComment", req.getRefundComment());
        updateOrder.set("updatedTime", new Date());
//        退款状态,0:未退款,1:退款申请,2:退款中,3:退款完成,4:待返货,7:部分退款中
        updateOrder.set("refundStatus", "0");
        UpdateResult updateResultOrder = mongoTemplate.updateFirst(query, updateOrder, OrderInfo.class);
        log.info(":>>> 订单:{} 的退款预操作结果:{}", req.getId(), updateResultOrder.getModifiedCount() > 0 ? true : false);

        Query query1 = new Query().addCriteria(Criteria.where("orderNo").is(orderInfo.getOrderNo()));
        Update updateD = new Update();
        updateD.set("verifyStatus", 0);
        updateD.set("status", "1");
        updateD.set("refundStatus", "0");
        updateD.set("refundFee", 0);
        updateD.set("updatedTime", new Date());
        mongoTemplate.updateFirst(query1, updateD, SubOrderInfo.class);
        UpdateResult updateResultD = mongoTemplate.updateFirst(query1, updateD, OrderInfo.class);
        log.info(":>>> 订单:{} 的退款操作结果:{}", req.getId(), updateResultD.getModifiedCount() > 0 ? true : false);
        return updateResultD.getModifiedCount() > 0 ? true : false;
    }

    /**
     * 设置子订单提示语
     *
     * @param orderInfo
     */
    private void setSubOrderTips(OrderInfo orderInfo) {
        if (Objects.isNull(orderInfo) || StringUtils.isBlank(orderInfo.getStatus()) || org.springframework.util.CollectionUtils.isEmpty(orderInfo.getOOrderInfos())) {
            log.info(":>>>  设置子订单编号错误:订单信息、订单状态、子订单集合为空");
            return;
        }
        for (OOrderInfo oOrderInfo : orderInfo.getOOrderInfos()) {
            String tips = "";
            String status = oOrderInfo.getStatus();
            if (StringUtils.isNotBlank(orderInfo.getRefundStatus())) {
                switch (orderInfo.getRefundStatus()) {
                    case "2":
                        tips = "退款申请成功，原支付金额将于1-3个工作日到账，注意查收！";
                        oOrderInfo.setTips(tips);
                        return;
                    case "3":
                        tips = "用户申请退款,退款完成,请查看微信账单!";
                        oOrderInfo.setTips(tips);
                        return;
                    default:
                        break;
                }
            }
            if (StringUtils.isBlank(status)) {
                status = orderInfo.getStatus();
            }
            if ("1".equals(status)) {
                tips = "亲，您的商品需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
                if (Objects.nonNull(orderInfo.getPayTime())) {

                    if ((new Date().getTime() - orderInfo.getPayTime().getTime()) > 12 * 3600 * 1000L) {
                        orderInfo.setStatus("2");
                        tips = "亲，您的商品目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
                    }
                }
                OrderInfoTip orderInfoTip = orderInfoTipService.find(orderInfo.getOrderNo(), oOrderInfo.getOOrderNo());
                if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                    tips = orderInfoTip.getTips();
                    log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
                }

            } else if ("2".equals(status)) {
                tips = "亲，您的商品目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";

            } else if ("3".equals(orderInfo.getStatus())) {
                tips = "亲，您的商品目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";

            } else if ("4".equals(status)) {
                OrderInfoTip orderInfoTip = orderInfoTipService.find(orderInfo.getOrderNo(), oOrderInfo.getOOrderNo()
                        , Boolean.TRUE);
                if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                    tips = orderInfoTip.getTips();
                    log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
                } else {
                    tips = "您的商品已经发货，请注意查收！可点击下方按钮查看物流进度";
                }

            }
            oOrderInfo.setTips(tips);
        }
    }

    /**
     * 过滤收货地址
     *
     * @param address
     * @param province
     * @param city
     * @param area
     * @param mobile
     * @return
     */
    private String filterAddress(String address, String province, String city, String area, String mobile) {
        if (StringUtils.isBlank(address)) {
            return address;
        }
        if (address.contains(" ")) {
            address = address.trim();
            address = address.replace(" ", "");
        }

        if (address.contains(mobile)) {
            log.info(":>>> 地址包含手机号:{}", mobile);
            address = address.replace(mobile, "");
        }
        if (address.contains(province + city + area)) {
            address = address.replace(province + city + area, "");
            log.info(":>>> 地址包含省市区:{}", province + city + area);
        }
        if (dP.contains(province)) {
            if (address.contains(province + area)) {
                address = address.replace(province + area, "");
                log.info(":>>> 地址包含直辖市:{}", province + area);
            }
        }
        return address;
    }

    private Long getOrderCount() {
        String key = ORDER_COUNT;
        Object o = redisTemplate.opsForValue().get(key);
        log.info(":>>> 订单数量:{}", o);
        if (Objects.isNull(o)) {
            return null;
        }
        return (Long) o;
    }

    private void setOrderCount(Long count) {
        String key = ORDER_COUNT;
        redisTemplate.opsForValue().set(key, count+"", 300, TimeUnit.SECONDS);
        log.info(":>>> 设置订单数量:{}", count);
    }

    private void reDoSubOrder(String orderNo, String subOrderNo, String batchId, Date date) {
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo).and("oOrderNo").is(subOrderNo));
        OOrderInfo sub = mongoTemplate.findOne(query, OOrderInfo.class);
        if (Objects.isNull(sub)) {
            log.error(":>>> 子订单不存在:{},{}", orderNo, subOrderNo);
            return;
        }
        if (Objects.isNull(sub.getCaInfo())) {
            log.error(":>>> 子订单商品不存在:{},{}", orderNo, subOrderNo);
            return;
        }
        if (CollectionUtils.isEmpty(sub.getCaInfo().getGiftItems())) {
            log.error(":>>> 子订单商品不存在增品:{},{},itemId:{}", orderNo, subOrderNo,
                    sub.getCaInfo().getId());
        }

        for (GiftCaInfo g : sub.getCaInfo().getGiftItems()) {
            Query querySub = new Query();
            querySub.addCriteria(Criteria.where("orderNo").is(orderNo));
            querySub.addCriteria(Criteria.where("itemInfoId").is(g.getId()));
            Update update = new Update();
            update.set("realed", Boolean.TRUE);
            update.set("reDoBatchId", batchId);
            update.set("updatedTime", date);
            UpdateResult updateResult = mongoTemplate.updateMulti(querySub, update, OOrderInfo.class);
            log.info(":>>> 订单:{},子订单:{},的增品订单更新数量:{}",
                    orderNo, subOrderNo, updateResult.getModifiedCount());
        }

    }

}
